UI动效 09

  1. 1. Text UI动效——躲避鼠标
    1. 1.0.1. 实现思路
    2. 1.0.2. 效果图
    3. 1.0.3. 源代码

Text UI动效——躲避鼠标


实现思路

  • 其实很早之前做项目时已经做过3D场景中的力场效果,推广到2D鼠标交互,只要统一坐标系就好了,剩下就是按效果调参数了。

效果图



源代码

  • UI用:
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
using UnityEngine;

public class ForceFieldObj : MonoBehaviour
{
// 鼠标位置
private Vector3 center;
// 引力位置
private Vector3 gravitationPos;
[SerializeField, Header("力场半径")] private float forceRadius;
[SerializeField, Header("斥力")] private float repulsion;
[SerializeField, Header("吸引力")] private float targetAttractive;
[SerializeField, Header("吸引力缩放")] private float speed = 1f;
// 用于坐标系转换的相机
private Camera cam;
[SerializeField, Header("应用缩放效果")] private bool useScale;

void Start()
{
gravitationPos = transform.position;
cam = Camera.main;
}

void Update()
{
if (forceRadius == 0) return;
var inputMouse = Input.mousePosition;
center = new Vector3(inputMouse.x, inputMouse.y, 90);
center = cam.ScreenToWorldPoint(center);
center = new Vector3(center.x, center.y, 90);

var velocity = Vector3.zero;
var len = (transform.position - center).magnitude; // 计算距离
// 如果距离小于范围,就是处于力场之中
if (len < forceRadius)
{
var rate = (forceRadius - len) / forceRadius;
var intensity = repulsion * rate;
velocity += (transform.position - center) * intensity * Time.deltaTime; // 计算斥力
}

velocity += (gravitationPos - transform.position) * Time.deltaTime * targetAttractive * speed; // 计算引力

transform.position += velocity;

//计算大小,跟随物体与引力中心离的越近越小
transform.localScale = useScale ? Mathf.Clamp01((this.transform.position - center).magnitude / forceRadius) * Vector3.one : transform.localScale;
}
}
  • 3D物体用:
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
using UnityEngine;

public class ForceFieldObj3D : MonoBehaviour
{
private Transform center;
private Vector3 gravitationPos;
[SerializeField] public float forceRadius = 4;
[SerializeField] private float repulsion;
[SerializeField] private float targetAttractive;
[SerializeField] private float speed = 0.1f;

void Start()
{
gravitationPos = transform.position;
}

void Update()
{
if (forceRadius == 0) return;
var velocity = Vector3.zero;
var len = (transform.position - center.position).magnitude;
if (len < forceRadius)
{
var rate = (forceRadius - len) / forceRadius;
var intensity = repulsion * rate;
velocity += (transform.position - center.position) * intensity * Time.deltaTime;
}

velocity += (gravitationPos - transform.position) * Time.deltaTime * targetAttractive * speed;
transform.position += velocity;
transform.localScale = Mathf.Clamp01((transform.position - center.position).magnitude / forceRadius) * Vector3.one;
}
}