Unity GrabPack控制器脚本帮助

using UnityEngine;

public class GrabPackController : MonoBehaviour
{
    // 手臂状态Enum
    public enum HandState { Idle, Shooting, Returning }

    // 头的变换
    [Header("Hands")]
    public Transform blueHand;
    public Transform redHand;

    // 原点变换
    [Header("Origins")]
    public Transform blueOrigin;
    public Transform redOrigin;

    // 射击点变换
    [Header("Shoot Points")]
    public Transform blueShootPoint;
    public Transform redShootPoint;

    // 手枪变换
    [Header("Guns")]
    public Transform blueGun;
    public Transform redGun;

    // 线条渲染器
    [Header("Line Renderers")]
    public LineRenderer blueLine;
    public LineRenderer redLine;

    // 设定
    [Header("Settings")]
    public float shootDistance = 15f;
    public float speed = 25f;
    public float returnSpeed = 30f;

    // 手臂状态
    private HandState blueState = HandState.Idle;
    private HandState redState = HandState.Idle;

    // 目标点
    private Vector3 blueTarget;
    private Vector3 redTarget;

    // 抓取物体
    private GameObject blueGrabbed;
    private GameObject redGrabbed;

    // 主相机
    private Camera cam;

    // 手枪原位本地位置
    private Vector3 blueGunStartLocalPos;
    private Vector3 redGunStartLocalPos;

    // 用于开始
    private void Start()
    {
        cam = Camera.main;
        ResetBlue();
        ResetRed();
        // 保存本地位置(重要)
        blueGunStartLocalPos = blueGun.localPosition;
        redGunStartLocalPos = redGun.localPosition;
    }

    // 用于更新
    private void Update()
    {
        // 只有在空闲时才能射击
        if (Input.GetMouseButtonDown(0) && blueState == HandState.Idle)
            ShootBlue();
        if (Input.GetMouseButtonDown(1) && redState == HandState.Idle)
            ShootRed();
        HandleBlue();
        HandleRed();
        UpdateGunRotation();
        UpdateLines();
    }

    // 啟動藍色手臂
    void ShootBlue()
    {
        if (cam == null) return;
        blueGrabbed = null;
        // 射击点对齐
        Ray ray = cam.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f));
        RaycastHit hit;
        // Raycast距离
        if (Physics.Raycast(ray, out hit, shootDistance))
        {
            blueTarget = hit.point;
            // 检测是哪个物体
            if (hit.collider.CompareTag("Grabbable"))
                blueGrabbed = hit.collider.gameObject;
        }
        else
        {
            blueTarget = ray.origin + ray.direction * shootDistance;
        }
        blueState = HandState.Shooting;
    }

    // 处理蓝色手臂
    void HandleBlue()
    {
        switch (blueState)
        {
            case HandState.Shooting:
                // 把手臂移动到目标点
                blueHand.position = Vector3.MoveTowards(blueHand.position, blueTarget, speed * Time.deltaTime);
                // 到达目标点时射击结束
                if (Vector3.Distance(blueHand.position, blueTarget) < 0.1f)
                    blueState = HandState.Returning;
                break;
            case HandState.Returning:
                // 将手臂移动到原点
                blueHand.position = Vector3.MoveTowards(blueHand.position, blueOrigin.position, returnSpeed * Time.deltaTime);
                // 把抓取物体移动到手臂位置
                if (blueGrabbed != null)
                    blueGrabbed.transform.position = blueHand.position;
                // 到达原点时射击结束
                if (Vector3.Distance(blueHand.position, blueOrigin.position) < 0.05f)
                    ResetBlue();
                break;
        }
    }

    // 重置蓝色手臂
    void ResetBlue()
    {
        blueHand.position = blueOrigin.position;
        blueHand.rotation = blueOrigin.rotation;
        blueGrabbed = null;
        blueState = HandState.Idle;
    }

    // 啟動紅色手臂
    void ShootRed()
    {
        if (cam == null) return;
        redGrabbed = null;
        // 射击点对齐
        Ray ray = cam.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f));
        RaycastHit hit;
        // Raycast距离
        if (Physics.Raycast(ray, out hit, shootDistance))
        {
            redTarget = hit.point;
            // 检测是哪个物体
            if (hit.collider.CompareTag("Grabbable"))
                redGrabbed = hit.collider.gameObject;
        }
        else
        {
            redTarget = ray.origin + ray.direction * shootDistance;
        }
        redState = HandState.Shooting;
    }

    // 处理红色手臂
    void HandleRed()
    {
        switch (redState)
        {
            case HandState.Shooting:
                // 把手臂移动到目标点
                redHand.position = Vector3.MoveTowards(redHand.position, redTarget, speed * Time.deltaTime);
                // 到达目标点时射击结束
                if (Vector3.Distance(redHand.position, redTarget) < 0.1f)
                    redState = HandState.Returning;
                break;
            case HandState.Returning:
                // 将手臂移动到原点
                redHand.position = Vector3.MoveTowards(redHand.position, redOrigin.position, returnSpeed * Time.deltaTime);
                // 把抓取物体移动到手臂位置
                if (redGrabbed != null)
                    redGrabbed.transform.position = redHand.position;
                // 到达原点时射击结束
                if (Vector3.Distance(redHand.position, redOrigin.position) < 0.05f)
                    ResetRed();
                break;
        }
    }

    // 重置红色手臂
    void ResetRed()
    {
        redHand.position = redOrigin.position;
        redHand.rotation = redOrigin.rotation;
        redGrabbed = null;
        redState = HandState.Idle;
    }

    // 更新枪位置
    void UpdateGunRotation()
    {
        // BLUE
        blueGun.localPosition = blueGunStartLocalPos;
        if (blueState == HandState.Shooting)
        {
            // 计算手臂和枪之间的方向
            Vector3 dir = blueHand.position - blueGun.position;
            if (dir != Vector3.zero)
            {
                Quaternion lookRot = Quaternion.LookRotation(dir);
                // 修复纵向90度
                blueGun.rotation = lookRot * Quaternion.Euler(-90f, 0f, 0f);
            }
        }
        // RED
        redGun.localPosition = redGunStartLocalPos;
        if (redState == HandState.Shooting)
        {
            // 计算手臂和枪之间的方向
            Vector3 dir = redHand.position - redGun.position;
            if (dir != Vector3.zero)
            {
                Quaternion lookRot = Quaternion.LookRotation(dir);
                // 修复纵向90度
                redGun.rotation = lookRot * Quaternion.Euler(-90f, 0f, 0f);
            }
        }
    }

    // 更新线条
    void UpdateLines()
    {
        if (blueLine != null)
        {
            if (blueState != HandState.Idle)
            {
                blueLine.enabled = true;
                blueLine.SetPosition(0, blueShootPoint.position);
                blueLine.SetPosition(1, blueHand.position);
            }
            else
                blueLine.enabled = false;
        }
        if (redLine != null)
        {
            if (redState != HandState.Idle)
            {
                redLine.enabled = true;
                redLine.SetPosition(0, redShootPoint.position);
                redLine.SetPosition(1, redHand.position);
            }
            else
                redLine.enabled = false;
        }
    }
}