UIToolKit|03 技巧
3D坐标转2D坐标
RuntimePanelUtils.CameraTransformWorldToPanel
随便新建一个血条
public class Test : MonoBehaviour
{
public UIDocument document;
public Transform head;
private VisualElement visualElement;
private void Start()
{
visualElement = document.rootVisualElement.Q<VisualElement>("hp");
}
private void Update()
{
visualElement.transform.position =
RuntimePanelUtils.CameraTransformWorldToPanel(visualElement.panel, head.position, Camera.main);
}
}
拖动事件
新建一个300x300的图片
public class Test : MonoBehaviour
{
public UIDocument document;
private VisualElement visualElement;
private bool moving;
private void Start()
{
visualElement = document.rootVisualElement.Q<VisualElement>("hp");
visualElement.RegisterCallback<PointerDownEvent>(OnPointerDown);
visualElement.RegisterCallback<PointerMoveEvent>(OnPointerMove);
visualElement.RegisterCallback<PointerUpEvent>(OnPointerUp);
}
private void OnPointerDown(PointerDownEvent evt)
{
moving = true;
}
private void OnPointerMove(PointerMoveEvent evt)
{
if (moving)
{
// Unity屏幕坐标的原点是左下角,而UIToolKit的原点是左上角,也就是说Y是相反的
var pos = new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y);
//转换自适应后的UI坐标
pos = RuntimePanelUtils.ScreenToPanel(visualElement.panel, pos);
//图片尺寸是300,这里取中心点
float widthAndHeight = 300f;
pos.x -= widthAndHeight / 2f;
pos.y -= widthAndHeight / 2f;
//设置坐标
visualElement.transform.position = pos;
}
}
private void OnPointerUp(PointerUpEvent evt)
{
moving = false;
}
}
动态设置样式
使用UGUI时,如果某一个元素需要改变多个样式,比如颜色,坐标,显隐等,那么我们可能需要写很多if else
if(??)
{
button.color = xxx;
image.position = xxx;
gameobject.active = false;
}
else
{
button.color = xxx;
image.position = xxx;
gameobject.active = true;
}
在UIToolKit中,则可以直接采用两套样式设计
新建一个简单的UXML
创建第一个USS
#text,代表选中所有名称为text的组件
还有其他很多种索引方式
再创建第二个USS
回到代码里,很简单
public class Test : MonoBehaviour
{
public UIDocument document;
public StyleSheet sheet1;
public StyleSheet sheet2;
private void Start()
{
var root = document.rootVisualElement;
root.Q<Button>("btn1").clicked += () =>
{
root.styleSheets.Remove(sheet2);
root.styleSheets.Add(sheet1);
};
root.Q<Button>("btn2").clicked += () =>
{
root.styleSheets.Remove(sheet1);
root.styleSheets.Add(sheet2);
};
}
}
不过目前USS好像对VisualElement不生效
界面动画
相当于内置了DoTween
public class Test : MonoBehaviour
{
public UIDocument document;
private void Start()
{
var root = document.rootVisualElement;
var text = root.Q<Label>("text");
root.Q<Button>("btn1").clicked += () =>
{
text.experimental.animation.Scale(2f, 2000).Ease(Easing.InSine);
};
}
}
但是比较有限,目前来看和DoTween差远了
编辑器界面
首先可以打开编辑器专用脚本
然后随便拼一个简单UXML
脚本如下
public class TestEditor : EditorWindow
{
[MenuItem("UIToolkit/Test")]
public static void GetWindow()
{
TestEditor wnd = GetWindow<TestEditor>();
wnd.titleContent = new GUIContent("ShowExample16");
}
public void OnEnable()
{
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/UXML.uxml");
rootVisualElement.Add(visualTree.Instantiate());
rootVisualElement.Q<Button>().clicked += () =>
{
Debug.Log(rootVisualElement.Q<IntegerField>().value);
};
}
}
Inspector界面
随便写一个Mono脚本
public class Test : MonoBehaviour
{
public int a;
public bool b;
public GameObject c;
}
拼一个对应的UXML
Binding Path就是代码中的变量名
对于Object这样的引用类型,还需要设置他的Type,和我们自己写编辑器脚本一样,ObjectField要有TypeOf
然后就大功告成了