向量在Unity中的使用
向量计算
二维向量 Vector2
Vector2.Angel 角度
Vector2.Angel(Vector2 from, Vector2 to)
返回from和to之间以度为单位的值
Vector2 from = new Vector2(-1, 0);
Vector2 to = new Vector2(0, 10);
float dir = Vector2.Angle(from, to);
// dir = 90
Vector2.ClampMagnitude 范围内的向量
Vector2.ClampMagnitude(Vector2 vector, float maxLength);
返回向量vector的副本,最大不超过maxLength
Vector2 from = new Vector2(1, 1);
Vector2 to = new Vector2(10, 10);
Vector2 clm = Vector2.ClampMagnitude(to, 5.0f);
// clm = (3.5, 3.5)
Vector2.Distance 距离
Vector2.Distance(Vector2 from, Vector2 to)
计算from和to之间的距离
Vector2 from = new Vector2(1, 1);
Vector2 to = new Vector2(10, 10);
float dis = Vector2.Distance(from, to);
// dis = 12.72792
Vector2.Dot 点乘
Vector2.Dot(Vector2 lhs, Vector2 rhs)
lhs和rhs的点乘积
Vector2 from = new Vector2(1, 1);
Vector2 to = new Vector2(10, 10);
float dot = Vector2.Dot(from, to);
Debug.Log(">>" + dot);
// dot = 20
Vector2.Lerp & Vector2.LerpUnclamped插值
Vector2.Lerp(Vector2 a, Vector2 b, float t);
向量a和b之间的线性插值,比例t
Vector2 from = new Vector2(1, 1);
Vector2 to = new Vector2(10, 10);
Vector2 lerp = Vector2.Lerp(from, to, .1f);
Vector2 lerpu = Vector2.LerpUnclamped(from, to, .1f);
// lerp = (1.9, 1.9)
// lerpu = (1.9, 1.9)
Vector2.Max & Min 最大&最小分量值
Vector2.Max(Vector2 lhs, Vector2 rhs);
返回由两个向量的最大分量组成的向量。
Vector2.Max(Vector2 lhs, Vector2 rhs);
返回由两个向量的最小分量组成的向量。
Vector2 from = new Vector2(1, 1);
Vector2 to = new Vector2(10, 10);
Vector2 max = Vector2.Max(from, to);
Vector2 min = Vector2.Min(from, to);
// max = (10.0, 10.0)
// min = (1.0, 1.0)
Vector2.MoveTowards 移动分量
Vector2.MoveTowards(Vector2 current, Vector2 target, float maxDistanceDelta);
向目标移动最大距离为maxDistanceDelta的一个点
Vector2 from = new Vector2(1, 1);
Vector2 to = new Vector2(10, 10);
for (int i = 0; i < 3; i++)
{
from = Vector2.MoveTowards(from, to, .5f);
// from = (1.4, 1.4) (1.7, 1.7) (2.1, 2.1)
}
Normalize 归一化
vector2.Normalize();
使向量vector2的大小为1
Vector2 from = new Vector2(1, 1);
Vector2 to = new Vector2(10, 10);
from.Normalize();
// from = (0.7, 0.7)
Vector2.SignedAngle 角度
Vector2.SignedAngle(Vector2 from, Vector2 to);
返回from和to之间以度为单位的角度
Vector2 dir_from = new Vector2(-1, 1);
Vector2 dir_to = new Vector2(10, 10);
float sa = Vector2.SignedAngle(dir_from, dir_to);
//sa = -90;
Gizmos.color = Color.red;
Gizmos.DrawLine(Vector2.zero, dir_from);
Gizmos.color = Color.green;
Gizmos.DrawLine(Vector2.zero, dir_to);
Vector2.Scale 缩放
Vector2.Scale(Vector2 a, Vector2 b);
按照向量b等比缩放向量a
Vector2 dir_from = new Vector2(-1, 1);
Vector2 dir_to = new Vector2(5, 5);
Vector2 dir = dir_from - dir_to;
// dir = (-6.0, -4.0)
Vector2 sc = Vector2.Scale(dir, new Vector2(2, 2));
// sc = (-12.0, -8.0)
Vector2.Perpendicular 垂直向量
Vector2.Perpendicular(Vector2 inDirection);
返回垂直于此2D向量的2D向量
Vector2 from = new Vector2(1, 1);
Vector2 to = new Vector2(10, 10);
Vector2 pc = Vector2.Perpendicular(to - from);
// pc = (-9.0, 9.0)
Gizmos.color = Color.red;
Gizmos.DrawLine(from, to);
Gizmos.color = Color.green;
Gizmos.DrawLine(Vector2.zero, pc);
Vector2.Reflect 反射向量
Vector2.Reflect(Vector2 inDirection, Vector2 inNormal);
将向量反射到由法线定义的向量上
Vector2 from = new Vector2(1, 1);
Vector2 to = new Vector2(10, 10);
Vector2 rf = Vector2.Reflect((from - to), new Vector2(0, 1));
// rf = (-9.0, 9.0)
Gizmos.color = Color.red;
Gizmos.DrawLine(from, to);
Gizmos.color = Color.yellow;
Gizmos.DrawLine(Vector2.zero, new Vector2(0, 1));
Gizmos.color = Color.green;
Gizmos.DrawLine(Vector2.zero, rf);
Vector2.SmoothDamp 平滑阻尼
Vector2.SmoothDamp(Vector2 current, Vector2 target, ref Vector2 currentVelocity, float smoothTime, float maxSpeed);
朝向目标,随着时间逐渐改变一个向量
其他 + - * /
三维向量
Vector3.Angle 角度
Vector3.Angle(Vector3 from, Vector3 to);
返回两个三维向量的角度
Vector3. ClampMagnitude 范围内的向量
Vector3.ClampMagnitude(Vector3 vector, float maxLength);
返回vector的副本,其大小限制为maxLength
Vector3.Cross 叉乘
Vector3.Cross(Vector3 a Vector3 b);
两个向量的叉乘
得到得结果永远是垂直于lhs和rhs所在得平面
根据叉乘的正负值来判断向量a,b的相对位置,即向量b是处于向量a的顺时针方向还是逆时针方向。
Vector3.Dot 点乘
Vector3.Dot (Vector3 lhs, Vector3 rhs);
返回两个向量的点乘
通过点积的计算我们可以简单判断当前物体是否朝向另外一个物体,计算当前物体的transform.forward向量与 (target.transform.position – transform.position)的点积即可, 大于0则面对,否则则背对着。这个计算也会有一点误差但大致够用
二级目录
摇杆控制
效果图
代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class RockerCtrl : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
// 圆形底图
RectTransform _img_rocker_bg;
// 弧形指针
Transform _img_pointer;
// 圆形摇杆
Image _img_rocker;
[SerializeField]
private PlayerCtrl _playerCtrl;
private bool _isPress = false;
private void Awake()
{
_img_rocker_bg = transform.GetComponent<RectTransform>();
_img_pointer = transform.GetChild(0);
_img_rocker = transform.GetChild(1).GetComponent<Image>();
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (_isPress) updateRockerPos();
}
public void OnPointerDown(PointerEventData eventData)
{
// Debug.Log("OnPointerDown:" + eventData.pointerCurrentRaycast.gameObject.name);
if (eventData.pointerCurrentRaycast.gameObject.name == _img_rocker.gameObject.name)
{
_isPress = true;
}
}
public void OnPointerUp(PointerEventData eventData)
{
// Debug.Log("OnPointerUp:" + eventData.ToString());
_isPress = false;
_img_pointer.gameObject.SetActive(false);
_img_rocker.transform.localPosition = Vector3.zero;
_playerCtrl.movePlayer(Vector2.zero, 0);
}
private void updateRockerPos()
{
// 相机透视模式(Perspective)下的摇杆
// 计算鼠标移动的向量长度
Vector2 dis = Vector2.ClampMagnitude((new Vector2(Input.mousePosition.x, Input.mousePosition.y)
- new Vector2(_img_rocker_bg.transform.position.x, _img_rocker_bg.transform.position.y)), _img_rocker_bg.sizeDelta.x * .5f);
_img_rocker.transform.localPosition = dis;
// 判断方向
float dir = (dis.x > 0) ? -1.0f : 1.0f;
// 计算旋转的角度
float rotate = Vector3.Angle(Vector3.up, dis) * dir;
_img_pointer.gameObject.SetActive(true);
_img_pointer.localRotation = Quaternion.Euler(0, 0, rotate);
Debug.Log("角度" + rotate);
// 移动,旋转玩家角色
_playerCtrl.movePlayer(dis, rotate);
// 相机正交模式(Orthographic)下的摇杆
// Vector2 dis = Vector2.ClampMagnitude((new Vector2(Input.mousePosition.x, Input.mousePosition.y) - new Vector2(_img_rocker_bg.transform.localPosition.x + Screen.width *.5f, _img_rocker_bg.transform.localPosition.y + Screen.height * .5f)), _img_rocker_bg.sizeDelta.x * .5f);
// _img_rocker.transform.localPosition = dis;
}
}
玩家控制
效果图
代码
public void movePlayer(Vector2 move, float rotate)
{
Vector3 _dir = move * Time.deltaTime * _speed;
transform.position += _dir;
_pointer.localRotation = Quaternion.Euler(0, 0, rotate);
}