You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
431 lines
12 KiB
431 lines
12 KiB
/* |
|
* 程序功能: |
|
* 设置手臂的行为 action |
|
* 设置手臂的帧序列 frameIndex |
|
*/ |
|
using System; |
|
using UnityEngine; |
|
/// <summary> |
|
/// 手臂动作帧 |
|
/// </summary> |
|
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<ArmAction>(); |
|
} |
|
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 |
|
/// <summary> |
|
/// 根据坐标行动作 |
|
/// </summary> |
|
/// <param name="position">坐标</param> |
|
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); |
|
} |
|
/// <summary> |
|
/// 复位 |
|
/// </summary> |
|
public void ResetArm() |
|
{ |
|
Init(Vector3.zero, true); |
|
} |
|
/// <summary> |
|
/// 停止动作 |
|
/// </summary> |
|
public void Stop() |
|
{ |
|
IsFinished = true; |
|
} |
|
/// <summary> |
|
/// 动作完成,执行下一个动作 |
|
/// </summary> |
|
public void Finished() |
|
{ |
|
Stop(); |
|
if (OnFinished != null) |
|
{ |
|
OnFinished(); |
|
} |
|
} |
|
/// <summary> |
|
/// 帧更新 |
|
/// </summary> |
|
void Update() |
|
{ |
|
if (!IsFinished) |
|
{ |
|
Move(); |
|
} |
|
} |
|
/// <summary> |
|
/// |
|
/// </summary> |
|
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 |
|
} |
|
} |
|
/// <summary> |
|
/// 向下降低Bi1 |
|
/// </summary> |
|
/// <param name="speed"></param> |
|
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); |
|
} |
|
/// <summary> |
|
/// 向上抬起Bi1 |
|
/// </summary> |
|
/// <param name="speed"></param> |
|
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); |
|
} |
|
/// <summary> |
|
/// 初始化所有方位的旋转量 |
|
/// </summary> |
|
private void InitAllDir() |
|
{ |
|
if (isRestPosition) |
|
{ |
|
quaternion = resetRotation; |
|
} |
|
else |
|
{ |
|
var targetDir = targetPosition - transform.position; |
|
var forward = transform.forward; |
|
newDir = targetDir; |
|
quaternion = Quaternion.LookRotation(newDir); |
|
} |
|
} |
|
/// <summary> |
|
/// 初始化垂直方向旋转量 |
|
/// </summary> |
|
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; |
|
} |
|
} |
|
/// <summary> |
|
/// 初始化水平方向旋转量 |
|
/// </summary> |
|
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); |
|
} |
|
} |
|
} |
|
/// <summary> |
|
/// 初始化移动信息 |
|
/// </summary> |
|
private void InitTarnslateToForward() |
|
{ |
|
if (isRestPosition) |
|
{ |
|
targetPosition = transform.position; |
|
} |
|
} |
|
/// <summary> |
|
/// 验证旋转角度 |
|
/// </summary> |
|
/// <param name="x"></param> |
|
/// <returns></returns> |
|
protected float CheckValue(float x) |
|
{ |
|
if (x >= 180 && x <= 360) |
|
{ |
|
x = x - 360; |
|
} |
|
return x; |
|
} |
|
} |
|
/// <summary> |
|
/// 动作类型 |
|
/// </summary> |
|
public enum ActionType |
|
{ |
|
/// <summary> |
|
/// 朝向举臂 |
|
/// </summary> |
|
RotateToTarget, |
|
/// <summary> |
|
/// 垂直举臂 |
|
/// </summary> |
|
RotateToTargetVertacal, |
|
/// <summary> |
|
/// 水平举臂 |
|
/// </summary> |
|
RotateToTargetHorizatal, |
|
/// <summary> |
|
/// 伸缩举臂 |
|
/// </summary> |
|
TranlateToForward, |
|
/// <summary> |
|
/// 根据距离旋转高度 |
|
/// </summary> |
|
RotateVertacalWithDistance |
|
}
|
|
|