PUN ☀️六、机器人基础设置:运动、相机、攻击与生命值
文章目錄
- 🟥 效果展示
- 🟧 機(jī)器人運動
- 1?? 狀態(tài)機(jī)及狀態(tài)機(jī)控制
- 2?? 添加角色控制器
- 3?? 制作預(yù)制體
- 🟨 相機(jī)跟隨
- 🟩 攻擊系統(tǒng)
- 1?? 激光射線
- 2?? 碰撞器設(shè)置
- 3?? 激光控制
- 4?? 預(yù)制體Apply一下
- 🟦 生命值系統(tǒng)
🟥 效果展示
首先,將PUN設(shè)為離線模式,先來進(jìn)行本地測試。等發(fā)布時,再取消勾選改為聯(lián)網(wǎng)模式。
為什么設(shè)置,可參考:傳送門
🟧 機(jī)器人運動
Robot Kyle 從Assets拖到層級面板,進(jìn)行如下配置:
1?? 狀態(tài)機(jī)及狀態(tài)機(jī)控制
a、指定機(jī)器人狀態(tài)機(jī):Kyle Robot
b、掛載如下代碼:
該代碼負(fù)責(zé)控制機(jī)器人運動,WAD運動,跑起來后右鍵跳躍。
using Photon.Pun; using UnityEngine;public class PlayerAnimatorManager : MonoBehaviourPun {#region Private Fields[SerializeField]float directionDampTime = 0.25f;Animator animator;#endregion#region Mono CallBacksvoid Start(){animator = GetComponent<Animator>();}void Update(){//教程參考:https://skode.blog.csdn.net/article/details/106356112if (PhotonNetwork.IsConnected == true && photonView.IsMine == false)return;AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);// 只有在我們跑步的時,按下右鍵才允許跳躍。if (stateInfo.IsName("Base Layer.Run") && Input.GetButtonDown("Fire2"))animator.SetTrigger("Jump");float h = Input.GetAxis("Horizontal");float v = Input.GetAxis("Vertical") < 0 ? 0 : Input.GetAxis("Vertical");animator.SetFloat("Speed", h * h + v * v);animator.SetFloat("Direction", h, directionDampTime, Time.deltaTime);}#endregion }2?? 添加角色控制器
為機(jī)器人添加 CharacterController,調(diào)整Center等,屬性如下:
3?? 制作預(yù)制體
創(chuàng)建 Resources 文件夾,將Robot Kyle拖到Resources制成預(yù)制體。
🟨 相機(jī)跟隨
為機(jī)器人添加如下腳本,勾選 FollwOnStart
該腳本的FollowOnStart,為離線模式,該功能是在離線模式下,讓攝像機(jī)自動找到人物跟隨。在發(fā)布時的聯(lián)網(wǎng)狀態(tài)下,需取消勾選,自己寫代碼判斷哪個人物是自己的,來跟隨。
你的Camera要為 MainCamera
using UnityEngine;// Camera work. Follow a target public class Skode_CameraWork : MonoBehaviour {#region Fields[Tooltip("在局部x-z平面到目標(biāo)的距離")]public float distance = 7.0f;[Tooltip("我們希望相機(jī)高于目標(biāo)的高度")]public float height = 3.0f;[Tooltip("相機(jī)高度的平滑時滯")]public float heightSmoothLag = 0.3f;[Tooltip("允許相機(jī)垂直于目標(biāo),例如,提供更多的景色和較少的地面")]public Vector3 centerOffset = Vector3.zero;[Tooltip("如果預(yù)制組件被光子網(wǎng)絡(luò)改變,則將此設(shè)置為false,并在需要時手動調(diào)用OnStartFollowing()")]public bool followOnStart = false;// cached transform of the targetTransform cameraTransform;// maintain a flag internally to reconnect if target is lost or camera is switchedbool isFollowing;// Represents the current velocity, this value is modified by SmoothDamp() every time you call it.float heightVelocity;// Represents the position we are trying to reach using SmoothDamp()float targetHeight = 100000.0f;#endregion#region Mono Callbacksvoid Start(){// Start following the target if wanted.if (followOnStart)OnStartFollowing();}void LateUpdate(){// The transform target may not destroy on level load,// so we need to cover corner cases where the Main Camera is different everytime we load a new scene, and reconnect when that happensif (cameraTransform == null && isFollowing)OnStartFollowing();// only follow is explicitly declaredif (isFollowing)Apply();}#endregion#region Public Methods/// <summary>/// Raises the start following event./// Use this when you don't know at the time of editing what to follow, typically instances managed by the photon network./// </summary>public void OnStartFollowing(){cameraTransform = Camera.main.transform;isFollowing = true;// we don't smooth anything, we go straight to the right camera shotCut();}#endregion#region Private Methods/// <summary>/// Follow the target smoothly/// </summary>void Apply(){Vector3 targetCenter = transform.position + centerOffset;// Calculate the current & target rotation anglesfloat originalTargetAngle = transform.eulerAngles.y;float currentAngle = cameraTransform.eulerAngles.y;// Adjust real target angle when camera is lockedfloat targetAngle = originalTargetAngle;currentAngle = targetAngle;targetHeight = targetCenter.y + height;// Damp the heightfloat currentHeight = cameraTransform.position.y;currentHeight = Mathf.SmoothDamp(currentHeight, targetHeight, ref heightVelocity, heightSmoothLag);// Convert the angle into a rotation, by which we then reposition the cameraQuaternion currentRotation = Quaternion.Euler(0, currentAngle, 0);// Set the position of the camera on the x-z plane to:// distance meters behind the targetcameraTransform.position = targetCenter;cameraTransform.position += currentRotation * Vector3.back * distance;// Set the height of the cameracameraTransform.position = new Vector3(cameraTransform.position.x, currentHeight, cameraTransform.position.z);// Always look at the targetSetUpRotation(targetCenter);}/// <summary>/// Directly position the camera to a the specified Target and center./// </summary>void Cut(){float oldHeightSmooth = heightSmoothLag;heightSmoothLag = 0.001f;Apply();heightSmoothLag = oldHeightSmooth;}/// <summary>/// Sets up the rotation of the camera to always be behind the target/// </summary>/// <param name="centerPos">Center position.</param>void SetUpRotation(Vector3 centerPos){Vector3 cameraPos = cameraTransform.position;Vector3 offsetToCenter = centerPos - cameraPos;// Generate base rotation only around y-axisQuaternion yRotation = Quaternion.LookRotation(new Vector3(offsetToCenter.x, 0, offsetToCenter.z));Vector3 relativeOffset = Vector3.forward * distance + Vector3.down * height;cameraTransform.rotation = yRotation * Quaternion.LookRotation(relativeOffset);}#endregion }🟩 攻擊系統(tǒng)
1?? 激光射線
在機(jī)器人Head下新建如圖所示兩個cube作為激光射線
2?? 碰撞器設(shè)置
只使用一個Collider就好,并作為觸發(fā)器,避免作為碰撞器將別人碰飛
- 將右眼激光的Collider移除,左眼Collider拉大包裹住兩個cube
- 勾選Collider的 isTrigger
- 將帶Collider射線的tag設(shè)為 beam
3?? 激光控制
機(jī)器人添加下方腳本,并將Beams賦值給它
實現(xiàn):當(dāng)按下鼠標(biāo)左鍵,打開激光。松開左鍵,關(guān)閉激光。
在網(wǎng)絡(luò)中多人玩,還要考慮:
我按下了鼠標(biāo)左鍵,那場景中的各個機(jī)器人,怎么判斷我是屬于誰,你按下鼠標(biāo)左鍵我要不要執(zhí)行程序?
if (photonView.IsMine),便實現(xiàn)了此功能。判斷這個機(jī)器人是不是我的。是的話,執(zhí)行程序。
using UnityEngine; using Photon.Pun;public class PlayerManager : MonoBehaviour {#region Parameterspublic GameObject beams;//當(dāng)用戶開火時,為Truebool IsFiring;#endregion#region Mono CallBacksvoid Awake(){beams.SetActive(false);}void Update(){if (PhotonNetwork.IsConnected == true && photonView.IsMine)ProcessInputs();if (IsFiring != beams.activeSelf)beams.SetActive(IsFiring);}#endregion#region Private Methodsvoid ProcessInputs(){//鼠標(biāo)左鍵if (Input.GetButtonDown("Fire1"))IsFiring = true;if (Input.GetButtonUp("Fire1"))IsFiring = false;}#endregion }4?? 預(yù)制體Apply一下
🟦 生命值系統(tǒng)
目標(biāo):
當(dāng)射線擊中時,扣0.1血,一直擊中,每秒0.1。
當(dāng)生命值0時,離開房間。
1、GameManager改為單例
2、PlayerManager 更新如下:
using UnityEngine; using Photon.Pun;public class PlayerManager : MonoBehaviourPunCallbacks {#region Parameterspublic GameObject beams;public float Health = 1f;//當(dāng)用戶開火時,為Truebool IsFiring;#endregion#region Mono CallBacksvoid Awake(){beams.SetActive(false);}void Update(){if (Health <= 0f)GameManager.ins.Skode_LeaveRoom();if (PhotonNetwork.IsConnected == true && photonView.IsMine)ProcessInputs();if (IsFiring != beams.activeSelf)beams.SetActive(IsFiring);}#endregion#region Private Methodsvoid ProcessInputs(){//鼠標(biāo)左鍵if (Input.GetButtonDown("Fire1"))IsFiring = true;if (Input.GetButtonUp("Fire1"))IsFiring = false;}void OnTriggerEnter(Collider other){if (!photonView.IsMine && !other.CompareTag("beam"))return;Health -= 0.1f;}void OnTriggerStay(Collider other){if (!photonView.IsMine && !other.CompareTag("beam"))return;//乘以增量時間,防止因為幀率FPS不同,扣血不同(舉例:不乘,每幀執(zhí)行一次扣血,卡的人比流暢的人扣血少)Health -= 0.1f * Time.deltaTime;}#endregion }
大家還有什么問題,歡迎在下方留言!
如果你有 技術(shù)的問題 或 項目開發(fā)
都可以加下方聯(lián)系方式
和我聊一聊你的故事🧡
總結(jié)
以上是生活随笔為你收集整理的PUN ☀️六、机器人基础设置:运动、相机、攻击与生命值的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: panabit之PPPoE认证
- 下一篇: DENSE_RANK函数