/* * 程序功能: * 设置手臂的行为 action * 设置手臂的帧序列 frameIndex */ using System; using UnityEngine; /// /// 手臂动作帧 /// public class ArmActionFrame : MonoBehaviour { //动作类型 public ActionType action = ActionType.RotateToTarget; //序列 public int FrameIndex; //动作完成 public Action OnFinished; //模型轴向错误 public bool IsOpposite = false; //手臂长度偏移量 public int ArmLenthOffset = 16; //x轴旋转的最大角度 public float MaxRotateX = 0; public float MinRotateX = -84f; //臂长 public float Maxlength = 15.8f; public float Minlength = 0.01634139f; //动作是否完成 private bool IsFinished = true; //动作速度 public float Speed = 20; //目标点 private Vector3 targetPosition; //旋转的向量 private Vector3 newDir; //旋转量 private Quaternion quaternion; //根据距离旋转高度 public int Distance = 20; #region 移动的变量 //当前高度 private ArmAction manager; private void Awake() { manager = GetComponentInParent(); } public float CurrentHeight { set { if (value >= Maxlength) { value = Maxlength; Finished(); } if (value <= Minlength) { value = Minlength; Finished(); } transform.localPosition = new Vector3(transform.localPosition.x, transform.localPosition.y, value); #if UNITY_EDITOR Debug.DrawLine(manager.EndTrans.position, targetPosition, Color.yellow); #endif } get { return transform.localPosition.z; } } #endregion /// /// 根据坐标行动作 /// /// 坐标 public void Init(Vector3 position, bool isRest) { //停止当前动作 Stop(); //设置目标点,初始化信息 targetPosition = position; isRestPosition = isRest; switch (action) { case ActionType.RotateToTarget: InitAllDir(); break; case ActionType.RotateToTargetVertacal: InitVetacalDir(); break; case ActionType.RotateToTargetHorizatal: InitHorizatalDir(); break; case ActionType.TranlateToForward: InitTarnslateToForward(); break; case ActionType.RotateVertacalWithDistance: InitVetacalDistance(); break; } //动作开始 IsFinished = false; } private Vector3 resetPosition; private Quaternion resetRotation; private bool isRestPosition = false; private void Start() { //记录初始臂长 //resetPosition = transform.position; //记录初始水平角度 resetRotation = transform.localRotation; } public void Play(Vector3 position) { Init(position, false); } public void Play() { Init(manager.targetPosition, false); } /// /// 复位 /// public void ResetArm() { Init(Vector3.zero, true); } /// /// 停止动作 /// public void Stop() { IsFinished = true; } /// /// 动作完成,执行下一个动作 /// public void Finished() { Stop(); if (OnFinished != null) { OnFinished(); } } /// /// 帧更新 /// void Update() { if (!IsFinished) { Move(); } } /// /// /// private void Move() { if (action == ActionType.TranlateToForward) { //臂长 float d2E = Mathf.FloorToInt(Vector3.Distance(manager.EndTrans.position, manager.StartTrans.position)) + ArmLenthOffset; float d2T = Mathf.FloorToInt(Vector3.Distance(manager.StartTrans.position, targetPosition));//臂底端到目标的距离 if (d2E < d2T) { CurrentHeight += Time.deltaTime * Speed; } else if (d2E > d2T) { CurrentHeight -= Time.deltaTime * Speed; } else { Finished(); } } else if (action == ActionType.RotateVertacalWithDistance) { //复位 if (isRestPosition) { transform.localRotation = Quaternion.RotateTowards(transform.localRotation, quaternion, Time.deltaTime * Speed * 2); if (transform.localRotation == quaternion) { Finished(); } } else { //检查尾端与目标点距离 float distance = Mathf.Round(Vector3.Distance(manager.EndTrans.position, targetPosition)); float targetDistance = ArmLenthOffset + Distance; //Debug.Log(string.Format("距离:{0}-目标距离:{1}", distance, targetDistance)); //距离小的时候抬高 if (distance < targetDistance) { Raise(Time.deltaTime * Speed * 2); //Debug.Log("需要抬高"); } else if (distance > targetDistance) { Decline(Time.deltaTime * Speed * 2); //Debug.Log("需要降低"); } float x = CheckValue(transform.localEulerAngles.x); if (distance == targetDistance || x == MinRotateX || x == MaxRotateX) { Finished(); } } } else { //复位 if (isRestPosition) { transform.localRotation = Quaternion.RotateTowards(transform.localRotation, quaternion, Time.deltaTime * Speed * 2); if (transform.localRotation == quaternion) { Finished(); } } else { transform.rotation = Quaternion.RotateTowards(transform.rotation, quaternion, Time.deltaTime * Speed * 2); float x = CheckValue(transform.localEulerAngles.x); if (x < MinRotateX && !IsOpposite) { transform.localEulerAngles = new Vector3(MinRotateX, transform.localEulerAngles.y, transform.localEulerAngles.z); Finished(); return; } if (x > MaxRotateX & !IsOpposite) { transform.localEulerAngles = new Vector3(MaxRotateX, transform.localEulerAngles.y, transform.localEulerAngles.z); Finished(); return; } if (transform.rotation == quaternion) { Finished(); } } //Debug #if UNITY_EDITOR switch (action) { case ActionType.RotateToTarget: Debug.DrawRay(transform.position, newDir, Color.blue); break; case ActionType.RotateToTargetVertacal: Debug.DrawRay(transform.position, newDir, Color.green); break; case ActionType.RotateToTargetHorizatal: Debug.DrawRay(transform.position, newDir, Color.red); break; } #endif } } /// /// 向下降低Bi1 /// /// public void Decline(float speed) { float x = transform.localEulerAngles.x; float y = transform.localEulerAngles.y; x = CheckValue(x); x += speed; x = Mathf.Clamp(x, MinRotateX, MaxRotateX);//模型穿插,调整模型预设后,这里参数也跟着修改。 transform.localEulerAngles = new Vector3(x, y, 0); } /// /// 向上抬起Bi1 /// /// public void Raise(float speed) { float x = transform.localEulerAngles.x; float y = transform.localEulerAngles.y; x = CheckValue(x); x -= speed; x = Mathf.Clamp(x, MinRotateX, MaxRotateX);//模型穿插,调整模型预设后,这里参数也跟着修改。 transform.localEulerAngles = new Vector3(x, y, 0); } /// /// 初始化所有方位的旋转量 /// private void InitAllDir() { if (isRestPosition) { quaternion = resetRotation; } else { var targetDir = targetPosition - transform.position; var forward = transform.forward; newDir = targetDir; quaternion = Quaternion.LookRotation(newDir); } } /// /// 初始化垂直方向旋转量 /// private void InitVetacalDir() { if (isRestPosition) { quaternion = resetRotation; } else { Vector3 hightOffSetPosition = new Vector3(targetPosition.x, targetPosition.y, targetPosition.z); Vector3 targetDir = hightOffSetPosition - transform.position; newDir = targetDir - Vector3.Dot(targetDir, transform.right) * transform.right; if (IsOpposite) { float temp = Vector3.Angle(newDir, transform.forward); if (temp > 90f) { quaternion = Quaternion.LookRotation(-newDir, transform.up); } else { quaternion = Quaternion.LookRotation(-newDir, -transform.up); } } else { quaternion = Quaternion.LookRotation(newDir, transform.up); } } } public void InitVetacalDistance() { if (isRestPosition) { quaternion = resetRotation; } } /// /// 初始化水平方向旋转量 /// private void InitHorizatalDir() { if (isRestPosition) { quaternion = resetRotation; } else { // 底臂part1到目标位置的向量 Vector3 targetDir = targetPosition - transform.position; //【BiTar在底臂forward方向上的分向量】 = 【BiTar向量】 - 【BiTar在底臂up方向上的分向量】 newDir = targetDir - Vector3.Dot(targetDir, transform.up) * transform.up; //由BiTar的【forward分向量】和【up分向量组成的】 旋转量Quaternion if (IsOpposite) { float temp = Vector3.Angle(newDir, transform.forward); if (temp > 90f) { quaternion = Quaternion.LookRotation(-newDir, transform.up); } else { quaternion = Quaternion.LookRotation(-newDir, -transform.up); } } else { quaternion = Quaternion.LookRotation(newDir, transform.up); } } } /// /// 初始化移动信息 /// private void InitTarnslateToForward() { if (isRestPosition) { targetPosition = transform.position; } } /// /// 验证旋转角度 /// /// /// protected float CheckValue(float x) { if (x >= 180 && x <= 360) { x = x - 360; } return x; } } /// /// 动作类型 /// public enum ActionType { /// /// 朝向举臂 /// RotateToTarget, /// /// 垂直举臂 /// RotateToTargetVertacal, /// /// 水平举臂 /// RotateToTargetHorizatal, /// /// 伸缩举臂 /// TranlateToForward, /// /// 根据距离旋转高度 /// RotateVertacalWithDistance }