/*
* 程序功能:
* 设置手臂的行为 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
}