using ChivaXR; using Sirenix.OdinInspector; using System; using System.Collections; using System.Collections.Generic; #if UNITY_EDITOR using UnityEditor; #endif using UnityEngine; public class ToolAni_BanShou : ToolAnimationBase { #region 扳手交互参数 [LabelText("相对移动位置")] public Vector3 localMovePos = new Vector3(0, 0, 0); [LabelText("相对旋转角度")] public float rotAngle = 0; [LabelText("扳手单轮角度")] public float maxAngle = 40; [LabelText("运行时长(不包含工具动画)")] public float duration = 1; [LabelText("螺丝抬起高度")] public float moveHigh = 0.02f; [LabelText("共享锚点")] public SimpleMoveItem m_SimpleMoveItem; [InfoBox("开启后,工具会随所有锚点的中心点进行朝向校准,关闭则使用默认朝向")] [LabelText("是否开启工具校准")] public bool m_UseCenterReset = true; //工具锚点旋转角度 private float toolAnchorAngle = 0; private float timer = 0; private bool isLuoSiRot = true; private float toolHighLerp = 0; [HideInInspector] public Transform currentModel; [HideInInspector] public Transform currentModelAnchor; public Transform currentToolAnchor; #endregion public override void PlayUpdate(ToolAnimationItem toolAnimationItem, bool reverse) { if (currentToolAnchor != toolAnimationItem.toolAnchor) { PlayBanShouAnimationByFrame(currentModel, currentModelAnchor, currentToolAnchor, () => { toolAnimationItem.isPlaying = false; if (currentToolAnchor != null) { toolAnimationItem.Destroy(currentToolAnchor.gameObject); } currentModel.gameObject.SetActive(false); }); } else { PlayBanShouAnimationByFrame(toolAnimationItem.model.transform, toolAnimationItem.modelAnchor, toolAnimationItem.toolAnchor, () => { toolAnimationItem.isPlaying = false; currentToolAnchor.gameObject.SetActive(false); currentModel.gameObject.SetActive(false); }); } } public void PlayBanShouAnimationByFrame(Transform tmpModel, Transform tmpModelAnchor, Transform tmpToolAnchor, Action finishedCallBack) { if (isLuoSiRot) { if (toolAnchorAngle < maxAngle) { timer += Time.deltaTime; toolAnchorAngle += Mathf.Abs(rotAngle) * Time.deltaTime / duration; tmpModel.position = Vector3.Lerp(tmpModelAnchor.position, tmpModelAnchor.position + tmpModelAnchor.TransformDirection(localMovePos), timer / duration); tmpModel.rotation = tmpModelAnchor.rotation; tmpModel.RotateAround(tmpModelAnchor.position, tmpModelAnchor.TransformDirection(localMovePos), rotAngle * timer / duration); tmpToolAnchor.position = tmpModel.position; tmpToolAnchor.rotation = tmpModelAnchor.rotation; tmpToolAnchor.RotateAround(tmpModelAnchor.position, tmpModelAnchor.TransformDirection(localMovePos), toolAnchorAngle * (rotAngle > 0 ? 1 : -1)); } else { toolHighLerp += Time.deltaTime * 5; if (toolHighLerp > 1) { toolHighLerp = 1; isLuoSiRot = false; } tmpToolAnchor.position = Vector3.Lerp(tmpModel.position, tmpModel.position + tmpModelAnchor.TransformDirection(localMovePos).normalized * moveHigh, toolHighLerp); } } else //扳手回转 { if (toolAnchorAngle > 0) { toolAnchorAngle -= Mathf.Abs(rotAngle) * Time.deltaTime / duration; tmpToolAnchor.rotation = tmpModelAnchor.transform.rotation; tmpToolAnchor.RotateAround(tmpModelAnchor.position, tmpModelAnchor.TransformDirection(localMovePos), toolAnchorAngle * (rotAngle > 0 ? 1 : -1)); } else { toolHighLerp -= Time.deltaTime * 5; if (toolHighLerp < 0) { toolHighLerp = 0; isLuoSiRot = true; } tmpToolAnchor.transform.position = Vector3.Lerp(tmpModel.position, tmpModel.position + tmpModelAnchor.TransformDirection(localMovePos).normalized * moveHigh, toolHighLerp); } } if (timer > duration) { timer = 0; tmpModel.position = tmpModelAnchor.position; tmpModel.rotation = tmpModelAnchor.rotation; tmpToolAnchor.position = tmpModelAnchor.position; tmpToolAnchor.rotation = tmpModelAnchor.rotation; finishedCallBack?.Invoke(); } } public override void FinishedState(ToolAnimationItem toolAnimationItem, bool reverse) { toolAnimationItem.toolAnchor.gameObject.SetActive(false); timer = 0; StopPlay(toolAnimationItem, reverse); } public override void InitState(ToolAnimationItem toolAnimationItem, bool reverse) { toolAnimationItem.model.SetActive(true); if (currentModel != null) { currentModel.gameObject.SetActive(true); } if (currentToolAnchor != null) { if (currentToolAnchor == toolAnimationItem.toolAnchor) { currentToolAnchor.gameObject.SetActive(false); } else { toolAnimationItem.Destroy(currentToolAnchor.gameObject); } } } public override void PlayTrigger(ToolAnimationItem toolAnimationItem, bool reverse) { timer = 0; isLuoSiRot = true; toolAnchorAngle = 0; if (Application.isPlaying) { if (AnimationManager.Instance.AnimationActiveObj != null) { InitTargetToolAnchor(AnimationManager.Instance.AnimationActiveObj.transform.position, toolAnimationItem); } } else { #if UNITY_EDITOR if (Selection.activeGameObject != null) { InitTargetToolAnchor(Selection.activeGameObject.transform.position, toolAnimationItem); } else { InitTargetToolAnchor(toolAnimationItem.modelAnchor.position, toolAnimationItem); } #endif } } public override void StopPlay(ToolAnimationItem toolAnimationItem, bool reverse) { timer = 0; if (currentModel != null) { currentModel.position = currentModelAnchor.position; currentModel.rotation = currentModelAnchor.rotation; } if (currentToolAnchor != null) { currentToolAnchor.position = currentModelAnchor.position; currentToolAnchor.rotation = currentModelAnchor.rotation; } if (currentToolAnchor != toolAnimationItem.toolAnchor) { toolAnimationItem.isPlaying = false; if (currentToolAnchor != null) { toolAnimationItem.Destroy(currentToolAnchor.gameObject); } if (Application.isPlaying && currentModel != null) { currentModel.gameObject.SetActive(false); } } else { toolAnimationItem.isPlaying = false; currentToolAnchor.gameObject.SetActive(false); if (Application.isPlaying && currentModel != null) { currentModel.gameObject.SetActive(false); } } } /// /// 根据当前CheckPos选择的物体最近的锚点执行动画 /// /// public void InitTargetToolAnchor(Vector3 CheckPos, ToolAnimationItem toolAnimationItem) { currentModel = toolAnimationItem.model.transform; currentModelAnchor = toolAnimationItem.modelAnchor; Vector3 centerPoint = Vector3.zero; if (m_SimpleMoveItem != null) { foreach (var item in m_SimpleMoveItem.moveObjs) { centerPoint += item.Value.position; if (Vector3.Distance(item.Key.transform.position, currentModel.position) < 0.001f) continue; if (Vector3.Distance(CheckPos, currentModelAnchor.position) > Vector3.Distance(CheckPos, item.Value.position)) { currentModelAnchor = item.Value; currentModel = item.Key.transform; } } centerPoint = centerPoint / m_SimpleMoveItem.moveObjs.Count; } if (currentModelAnchor != toolAnimationItem.modelAnchor) { currentToolAnchor = GameObject.Instantiate(toolAnimationItem.toolAnchor); currentToolAnchor.transform.parent = currentModelAnchor; currentToolAnchor.transform.localPosition = Vector3.zero; currentToolAnchor.transform.localRotation = Quaternion.identity; currentToolAnchor.transform.localScale = Vector3.one; if (m_UseCenterReset) { float angle = Vector3.Angle(toolAnimationItem.modelAnchor.position - centerPoint, currentModelAnchor.position - centerPoint); Vector3 oldDir = currentModelAnchor.InverseTransformDirection(toolAnimationItem.modelAnchor.position - centerPoint); Vector3 newDir = currentModelAnchor.InverseTransformDirection(currentModelAnchor.position - centerPoint); float a = Vector3.Dot(Vector3.Cross(oldDir, newDir), localMovePos); for (int i = 0; i < currentToolAnchor.childCount; i++) { currentToolAnchor.GetChild(i).RotateAround(currentModelAnchor.position, currentModelAnchor.TransformDirection(localMovePos), angle * (a > 0 ? 1 : -1)); } } } else { currentToolAnchor = toolAnimationItem.toolAnchor; toolAnimationItem.toolAnchor.gameObject.SetActive(true); } currentToolAnchor.gameObject.SetActive(true); } #if UNITY_EDITOR public override void EditorPlayUpdate(ToolAnimationItem toolAnimationItem, bool reverse) { if (currentToolAnchor != toolAnimationItem.toolAnchor) { PlayBanShouAnimationByFrame(currentModel, currentModelAnchor, currentToolAnchor, () => { toolAnimationItem.isPlaying = false; if (currentToolAnchor != null) { toolAnimationItem.Destroy(currentToolAnchor.gameObject); } }); } else { PlayBanShouAnimationByFrame(toolAnimationItem.model.transform, toolAnimationItem.modelAnchor, toolAnimationItem.toolAnchor, () => { toolAnimationItem.isPlaying = false; }); } } public override void OnDrawGizmos(ToolAnimationItem toolAnimationItem) { Gizmos.color = Color.yellow; Gizmos.DrawLine(toolAnimationItem.modelAnchor.position, toolAnimationItem.modelAnchor.position + toolAnimationItem.modelAnchor.TransformDirection(localMovePos)); } #endif }