入門教程Blender+Unity從零開始做挖掘機模擬器游戲
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
?
?
/// <summary>
/// 配合InputSystem讀取玩家鍵鼠/手柄輸入
/// 把輸入轉(zhuǎn)化為二維向量和浮點值緩存到幾個公共變量中供其他腳本調(diào)用
/// </summary>
?
public class PlayerInput : MonoBehaviour
{
??? public Vector2 move;
??? public Vector2 look;
??? public float bigArm;
??? public float smallArm;
??? public float bucket;
??? public float baseRotate;
?
??? public void OnMove(InputValue value)
??? {
??????? move = value.Get<Vector2>();
??? }
?
??? public void OnLook(InputValue value)
??? {
??????? look = value.Get<Vector2>();
??? }
?
??? public void OnBigArm(InputValue value)
??? {
??????? bigArm = value.Get<float>();
??? }
??? public void OnSmallArm(InputValue value)
??? {
??????? smallArm = value.Get<float>();
??? }
??? public void OnBucket(InputValue value)
??? {
??????? bucket = value.Get<float>();
??? }
??? public void OnBaseRotate(InputValue value)
??? {
??????? baseRotate = value.Get<float>();
??? }
}

?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
?
?
/// <summary>
/// 控制挖掘機的各項功能
/// </summary>
?
public class PlayerController : MonoBehaviour
{
??? //變量定義區(qū)
??? private CharacterController characterController;
??? private PlayerInput playerInput;
?
??? [SerializeField]
??? private Transform cameraFollowObject;
?
??? [SerializeField]
??? private Driver bigArm;
??? [SerializeField]
??? private Driver smallArm;
??? [SerializeField]
??? private Driver bucket;
??? [SerializeField]
??? private Driver rotationBase;
?
??? [SerializeField]
??? private Animator leftTrack;
??? [SerializeField]
??? private Animator rightTrack;
?
??? public float speed = 10f;
??? public float turnSpeed = 50f;
?
??? private float xRotation;
??? private float yRotation;
??? private Vector3 gravity;
?
??? /// <summary>
??? /// 初始化CharacterController和PlayerInput組件
??? /// </summary>
?
??? private void Awake()
??? {
??????? characterController = GetComponent<CharacterController>();
??????? playerInput = GetComponent<PlayerInput>();
??? }
?
??? /// <summary>
??? /// 邏輯主循環(huán)
??? /// </summary>
?
??? void Update()
??? {
??????? //判斷是否著地
??????? //著地時沒有向下的速度,浮空時有向下的速度
?
??????? if (!characterController.isGrounded)
??????? {
??????????? gravity = Vector3.down * 100f;
??????? }
??????? else
??????? {
??????????? gravity = Vector3.zero;
??????? }
?
??????? //控制前進(jìn)后退
??????? //調(diào)用Move函數(shù),傳入一個向量,向量的方向為物體當(dāng)前朝向的正方向,向量的大小為玩家輸入*速度放大倍數(shù)*幀率調(diào)整系數(shù)
??????? //如果物體浮空還要加入向下的速度
?
??????? characterController.Move(transform.forward * playerInput.move.y * Time.deltaTime * speed + gravity * Time.deltaTime);
?
??????? //挖掘機只有左右履帶需要控制動畫播放
??????? leftTrack.SetFloat("LeftSpeed", playerInput.move.normalized.y);
??????? rightTrack.SetFloat("RightSpeed", playerInput.move.normalized.y);
?
??????? //控制挖掘機旋轉(zhuǎn)
??????? //當(dāng)玩家橫向輸入不為零時,y方向上旋轉(zhuǎn)物體,給左右履帶設(shè)定相反的播放速度
?
??????? if (playerInput.move.x != 0)
??????? {
??????????? transform.Rotate(0, playerInput.move.x * Time.deltaTime * turnSpeed, 0);
??????????? leftTrack.SetFloat("LeftSpeed", playerInput.move.normalized.x);
??????????? rightTrack.SetFloat("RightSpeed", -playerInput.move.normalized.x);
??????? }
?
??????? //控制機械驅(qū)動
??????? //分別控制大臂,小臂,挖斗,平臺旋轉(zhuǎn)
?
??????? bigArm.RotateComponent(playerInput.bigArm);
??????? smallArm.RotateComponent(playerInput.smallArm);
??????? bucket.RotateComponent(playerInput.bucket);
??????? rotationBase.RotateComponent(playerInput.baseRotate);
??? }
?
??? /// <summary>
??? /// 讀取玩家右搖桿/鼠標(biāo)的輸入向量,轉(zhuǎn)化為x和y兩個旋轉(zhuǎn)變量,旋轉(zhuǎn)相機跟隨物體
??? /// 其中對x方向上的旋轉(zhuǎn)要鉗制在一個范圍內(nèi)
??? /// 最終把x和y的旋轉(zhuǎn)量轉(zhuǎn)換為一個四元數(shù)
??? /// </summary>
?
??? private void LateUpdate()
??? {
??????? xRotation += playerInput.look.y;
??????? yRotation += playerInput.look.x;
?????? ?xRotation = Mathf.Clamp(xRotation, -30f, 60f);
??????? cameraFollowObject.rotation = Quaternion.Euler(xRotation, yRotation, 0);
??? }
}
?

System.Collections;
using System.Collections.Generic;
using UnityEngine;
?
/// <summary>
/// 控制挖掘機大臂小臂挖斗平臺旋轉(zhuǎn)
/// 這幾個部件分別都有一個最大旋轉(zhuǎn)值,最小旋轉(zhuǎn)值,旋轉(zhuǎn)速度屬性,旋轉(zhuǎn)軸,以及一個偏移向量
/// 設(shè)定一個旋轉(zhuǎn)函數(shù),按照玩家的輸入值來控制旋轉(zhuǎn)角度
/// </summary>
?
public class Driver : MonoBehaviour
{
??? [SerializeField]
??? private Vector3 Axis;
??? [SerializeField]
??? private Vector3 Offset;
??? [SerializeField]
??? private float minRotate;
??? [SerializeField]
??? private float maxRotate;
??? [SerializeField]
??? private float rotateSpeed = 10f;
?
??? private float rotationAmount;
?
??? public void RotateComponent(float playerInputValue)
??? {
???? ???rotationAmount += playerInputValue * Time.deltaTime * rotateSpeed;
??????? rotationAmount = Mathf.Clamp(rotationAmount, minRotate, maxRotate);
??????? transform.localRotation = Quaternion.Euler(Axis * rotationAmount + Offset);
??? }
}

?
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
?
?
/// <summary>
/// 當(dāng)檢測到挖掘機接觸時對外發(fā)出事件(up主給粉絲上傳視頻)
/// </summary>
public class ColliderMessenger : MonoBehaviour
{
??? public event Action OnCollapse;
??? private void OnTriggerEnter(Collider other)
??? {
??????? Debug.Log("hit");
??????? OnCollapse?.Invoke();
??????? Destroy(gameObject);
??? }
}
?
?

System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.InputSystem.XR;
?
?
/// <summary>
/// 事件接受者(粉絲訂閱up主的賬號,獲取up主發(fā)出的視頻)
/// </summary>
public class ColliderReceiver : MonoBehaviour
{
??? private Rigidbody rigidbody;
??? private ColliderMessenger colliderMessenger;
??? private void Awake()
??? {
??????? rigidbody = GetComponent<Rigidbody>();
??????? colliderMessenger = transform.parent.GetComponentInChildren<ColliderMessenger>();
??????? colliderMessenger.OnCollapse += Collapse;
??????? gameObject.SetActive(false);
??? }
?
??? private void Collapse()
??? {
??????? Debug.Log("collapsing");
??????? gameObject.SetActive(true);
??????? rigidbody.useGravity = true;
??? }
}
?