目录
1.飞行的实现
2.限制玩家视角
3.射击的实现
4.附录
(1)在Player预制体上挂载Configuration Joint组件,并修改其Y Drive属性
(2) 修改PlayerInput.cs和PlayerController.cs以实现飞行
添加以下属性
[SerializeField]
private float thrusterForce = 20f;
[SerializeField]
private ConfigurableJoint joint
在其Start方法中添加以下语句
joint = GetComponent();
在其Update方法中添加以下语句
Vector3 force = Vector3.zero;
if (Input.GetButton("Jump"))
{
force = Vector3.up * thrusterForce;
joint.yDrive = new JointDrive
{
positionSpring = 0f,
positionDamper = 0f,
maximumForce = 0f,
};
}
else
{
joint.yDrive = new JointDrive
{
positionSpring = 20f,
positionDamper = 0f,
maximumForce = 40f,
};
}
playerControllor.Thrust(force);
添加以下属性
private Vector3 thrusterForce = Vector3.zero;//向上的推力
添加以下方法
public void Thrust(Vector3 _thrusterForce)
{
thrusterForce = _thrusterForce;
}
在其PerformMovement方法中添加以下语句
if (thrusterForce != Vector3.zero)
{
rb.AddForce(thrusterForce);//作用Time.fixedDeltaTime秒:0.02秒
thrusterForce = Vector3.zero;
}
修改PlayerController.cs
添加以下属性
private float cameraRoatationTotal = 0f;//累计转了多少度
[SerializeField]
private float cameraRotationLimit = 85f;
对其PerformRotation方法进行一下修改
private void PerformRotation()
{
if (yRotation != Vector3.zero)
{
rb.transform.Rotate(yRotation);
}
if (xRotation != Vector3.zero)
{
cam.transform.Rotate(xRotation);
cameraRoatationTotal += xRotation.x;
cameraRoatationTotal = Mathf.Clamp(cameraRoatationTotal, -cameraRotationLimit, +cameraRotationLimit);
cam.transform.localEulerAngles = new Vector3(cameraRoatationTotal, 0f, 0f);
}
}
(1) 创建并编写PlayerWeapon.cs,将其移动至Assets/Scripts/Player
using System;
[Serializable]
public class PlayerWeapon
{
public string name = "M16";
public int damage = 10;
public float range = 100f;
}
(2)在场景中创建空物体“GameManager”,创建并编写GameManager.cs并挂载至空物体“GameManager”
using System;
using UnityEngine;
public class GameManager : MonoBehaviour
{
private static string info;
public static void UpdateInfo(String _info)
{
info = _info;
}
private void OnGUI()
{
GUILayout.BeginArea(new Rect(200f,200f,200f,400f));
GUILayout.BeginVertical();
GUILayout.Label(info);
GUILayout.EndVertical();
GUILayout.EndArea();
}
}
(3)创建并编写PlayerShooting.cs并将其挂载至Player预制体,将其移至Assets/Scripts/Player
using Unity.Netcode;
using UnityEngine;
public class PlayerShooting : NetworkBehaviour
{
[SerializeField]
private PlayerWeapon weapon;
[SerializeField]
private LayerMask mask;
private Camera cam;
// Start is called before the first frame update
void Start()
{
cam = GetComponentInChildren();
}
// Update is called once per frame
void Update()
{
if(Input.GetButton("Fire1"))
{
Shoot();
}
}
private void Shoot()
{
RaycastHit hit;
if (Physics.Raycast(cam.transform.position, cam.transform.forward, out hit,weapon.range,mask))
{
ShootServerRpc(hit.collider.name,weapon.damage);
}
}
[ServerRpc]
private void ShootServerRpc(string hittedName,int damage)
{
GameManager.UpdateInfo(transform.name+" hit "+hittedName);
}
}
(4) 修改NetworkUI.cs,实现“点击按钮后按钮消失”
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;
public class NetworkManagerUI : MonoBehaviour
{
[SerializeField]
private Button hostBtn;
[SerializeField]
private Button serverBtn;
[SerializeField]
private Button clientBtn;
// Start is called before the first frame update
void Start()
{
hostBtn.onClick.AddListener(() =>
{
NetworkManager.Singleton.StartHost();
DestroyAllButtons();
});
serverBtn.onClick.AddListener(() =>
{
NetworkManager.Singleton.StartServer();
DestroyAllButtons();
});
clientBtn.onClick.AddListener(() =>
{
NetworkManager.Singleton.StartClient();
DestroyAllButtons();
});
}
private void DestroyAllButtons()
{
Destroy(hostBtn.gameObject);
Destroy(serverBtn.gameObject);
Destroy(clientBtn.gameObject);
}
}
(1)测试效果图
(按住空格起飞,朝向任意碰撞体按下鼠标左键,屏幕左上方出现命中提示)
(2)部分工程文件完整代码
using UnityEngine;
public class PlayerInput : MonoBehaviour
{
[SerializeField]
private float speed = 5f;
[SerializeField]
private float thrusterForce = 20f;
[SerializeField]
private PlayerController playerControllor;
[SerializeField]
private float lookSensitivity = 8f;
[SerializeField]
private ConfigurableJoint joint;
// Start is called before the first frame update
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
joint = GetComponent();
}
// Update is called once per frame
void Update()
{
float xMov = Input.GetAxisRaw("Horizontal");
float yMov = Input.GetAxisRaw("Vertical");
Vector3 velocity = (transform.right * xMov + transform.forward * yMov).normalized*speed;
playerControllor.Move(velocity);
float xMouse = Input.GetAxisRaw("Mouse X");
float yMouse = Input.GetAxisRaw("Mouse Y");
Vector3 yRotation = new Vector3(0f, xMouse, 0f)*lookSensitivity;
Vector3 xRotation = new Vector3(-yMouse, 0f, 0f)*lookSensitivity;
playerControllor.Rotate(yRotation,xRotation);
Vector3 force = Vector3.zero;
if (Input.GetButton("Jump"))
{
force = Vector3.up * thrusterForce;
joint.yDrive = new JointDrive
{
positionSpring = 0f,
positionDamper = 0f,
maximumForce = 0f,
};
}
else
{
joint.yDrive = new JointDrive
{
positionSpring = 20f,
positionDamper = 0f,
maximumForce = 40f,
};
}
playerControllor.Thrust(force);
}
}
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField]
private Rigidbody rb;
[SerializeField]
private Camera cam;
private Vector3 velocity = Vector3.zero;//速度:每秒钟移动的距离
private Vector3 yRotation=Vector3.zero;//旋转角色
private Vector3 xRotation = Vector3.zero;//旋转视角
private float cameraRoatationTotal = 0f;//累计转了多少度
[SerializeField]
private float cameraRotationLimit = 85f;
private Vector3 thrusterForce = Vector3.zero;//向上的推力
public void Move(Vector3 _velocity)
{
velocity = _velocity;
}
public void Rotate(Vector3 _yRotation, Vector3 _xRotation)
{
yRotation = _yRotation;
xRotation = _xRotation;
}
public void Thrust(Vector3 _thrusterForce)
{
thrusterForce = _thrusterForce;
}
private void PerformMovement()
{
if (velocity != Vector3.zero)
{
rb.MovePosition(rb.position+velocity*Time.fixedDeltaTime);
}
if (thrusterForce != Vector3.zero)
{
rb.AddForce(thrusterForce);//作用Time.fixedDeltaTime秒:0.02秒
thrusterForce = Vector3.zero;
}
}
private void PerformRotation()
{
if (yRotation != Vector3.zero)
{
rb.transform.Rotate(yRotation);
}
if (xRotation != Vector3.zero)
{
cam.transform.Rotate(xRotation);
cameraRoatationTotal += xRotation.x;
cameraRoatationTotal = Mathf.Clamp(cameraRoatationTotal, -cameraRotationLimit, +cameraRotationLimit);
cam.transform.localEulerAngles = new Vector3(cameraRoatationTotal, 0f, 0f);
}
}
private void FixedUpdate()
{
PerformMovement();
PerformRotation();
}
}