FishPlayer

一个喜欢摸鱼的废物

0%

Unity动画控制Layout参数

在实际制作UI的时候,为了完成一些排版设计,我们会经常用到Unity的布局(Layout)组件。甚至有些复杂的排版,我会用嵌套布局来实现。
UI美术人经常希望在这些布局上加上一些进场出场动画(甚至包括spacing变动),但布局组件上的数值是没法在动画中修改的,怎么办呢?

方法一

在布局中添加一些空物体或是在布局外面套空物体。然后再使用Tween动画来完成UI美术们想要的那些进出场动画。
美术人不太喜欢的方法,因为有那么一点点不太方便和Animation直接一起预览,但如果整体进出场动画不依赖UnityAnimation且不是很复杂,这种方法完全够用。

方法二

用通过动画控制脚本上的可序列化的数值,再传递到布局组件上。
个人感觉这个方法也还不错,还能支持预览,UI美术更偏向于这一个解决方法。

但是在动画窗口里里看到的curve是锯齿状的,很奇怪。之后还需要看下如何才能像其他属性一样拉正常的曲线。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

using UnityEngine;
using UnityEngine.UI;

[ExecuteAlways]
public class LayoutGroupTempAnimationParam : MonoBehaviour
{
[SerializeField]
private LayoutGroup _target;

[SerializeField]
private int _left;
[SerializeField]
private int _right;
[SerializeField]
private int _top;
[SerializeField]
private int _bottom;

[Header("GridLayout must use GridSpacing")]
[SerializeField]
private bool _alsoControlSpacing;
[SerializeField]
private int _normalSpacing = 0;
[SerializeField]
private Vector2 _gridSpacing = Vector2.zero;

private RectOffset m_targetPadding;

public void OnDidApplyAnimationProperties()
{
if (_target == null)
{
return;
}
ApplyPadding();
if (_alsoControlSpacing)
{
ApplySpacing();
}
// need to notify refresh
RectTransform rectTransform = this.transform as RectTransform;
LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
}

private void ApplyPadding()
{
m_targetPadding = _target.padding;
if (m_targetPadding != null)
{
m_targetPadding.left = _left;
m_targetPadding.right = _right;
m_targetPadding.top = _top;
m_targetPadding.bottom = _bottom;
}
}

private void ApplySpacing()
{
if (_target is HorizontalOrVerticalLayoutGroup layoutGroup)
{
layoutGroup.spacing = _normalSpacing;
}
else if (_target is GridLayoutGroup gridLayoutGroup)
{
gridLayoutGroup.spacing = _gridSpacing;
}
}

#if UNITY_EDITOR

private void OnValidate()
{
ApplyPadding();
if (_alsoControlSpacing)
{
ApplySpacing();
}
if (!Application.isPlaying)
{
// need to notify refresh
RectTransform rectTransform = this.transform as RectTransform;
LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
}
}

private void Reset()
{
_target = this.GetComponent<LayoutGroup>();
m_targetPadding = _target.padding;
}

#endif
}