- 修改地图大小
- 限制相机度数
进入PlayerController类
private float cameraRotationTotal = 0f;//当前相机应该在的度数,不是向量,只是个一维的数据
[SerializeField]
private float cameraRotationLimit = 85f;//相机旋转限制
private void PerformRotation()
{
...
if(xRotation != Vector3.zero)
{
cameraRotationTotal += xRotation.x;//xRotion是每一帧相机向量,要加上.x
//Mathf.Clamp实现夹逼定理
cameraRotationTotal = Mathf.Clamp(cameraRotationTotal, -cameraRotationLimit, cameraRotationLimit);
//transform.localEulerAngles可以直接让当前相机的读数被赋值
cam.transform.localEulerAngles = new Vector3(cameraRotationTotal, 0f, 0f);
}
}
射击
先在Player添加一个PlayerShooting脚本,用来实现Player的射击
//由于PlayerInput,Controller内容有点多了,单独创建一个类来处理射击的输入,行动
public class PlayerShooting : MonoBehaviour
{
[SerializeField]
private PlayerWeapon weapon;
void Update()
{
//GetButtonDown()先设计一个单发的射击,便于调试
//去unity的project settings -> Input Manager里面看看Fire1的button
if (Input.GetButtonDown("Fire1")) {
}
}
}
-
改键
-
将武器的属性合并
类似于下图
先创建一个PlayerWeapon类
//可序列化
[Serializable]
//不用继承unity的基类MonoBehaviour
public class PlayerWeapon
{
public string name = "M16A1";
public int damage = 10;
public float range = 100f;
}
在PlayerShooting里面实例化PlayerWeapon
[SerializeField]
private PlayerWeapon weapon;
- 获取射击反馈信息
在PlayerShooting类里获取Player的眼睛
private Camera cam;
void Start()
{
//从当前组件的子组件里面找 Camera,也就是Player的眼睛
//射线实际上是player的眼睛里射出来的
cam = GetComponentInChildren<Camera>();
}
实现射击反馈信息的函数
由于手动实现射线命中物体很困难,可以学习unity自带的API,Physics.Raycast()
[SerializeField]
private LayerMask mask;
private void Shoot() {
//此为Raycast射中的物体,因为Physics.Raycast的返回值为bool类型
RaycastHit hit;
//Physics.Raycast对带有collider的物体进行信息反馈
//射出位置, 射出方向, 射中物体,射程,需要穿过的物体
if (Physics.Raycast(cam.transform.position, cam.transform.forward, out hit, weapon.range, mask)) {
Debug.Log(hit.collider.name);
}
}
调试时先将组件里面的mask调为everthing
-
将地图物品命名
-
给Player命名
由于每一个窗口的player都叫player(clone)无法做出区分
(可以进入Player下的任何一个脚本)
进入PlayerSetup
void Start()
{
...
//记得调用函数
SetPlayerName();
}
private void SetPlayerName() {
//组件NetworkObject会赋予一个唯一的id,保证在各个窗口的主player不一样并且同一个player的名字又一样
transform.name = "Player" + GetComponent<NetworkObject>().NetworkObjectId;
}
- 给服务器传消息
进入PlayerShooting类里
//使用ServerRpc是一种网络行为,所以要继承unity的基类NetworkBehaviour
public class PlayerShooting : NetworkBehaviour
{
...
private void Shoot() {
...
if (Physics.Raycast(cam.transform.position, cam.transform.forward, out hit, weapon.range, mask)) {
ShootServerRpc(hit.collider.name);
}
}
//有点糊,简单理解在服务器上调用
[ServerRpc]
private void ShootServerRpc(string hittedName) {
//输出谁击中了谁
Debug.Log(transform.name + "hit" + hittedName);
}
}
- 使窗口里其他的player不能都射击
点开Player Setup组件
添加PlayerShooting组件
*在游戏画面上输出一段调试信息
先在全局里创建一个GameManager的物体
再在这个物体里创建一个同名脚本
public class GameManager : MonoBehaviour
{
//画一段文字,info
private static string info;
//让外面的类可以通过UpdateInfo修改info
public void UpdateInfo(string _info) {
info = _info;
}
//渲染用户图形界面,OnGUI()每一帧都会自动渲染
private void OnGUI()
{
GUILayout.BeginArea(new Rect(400f, 400f, 200f, 400f));
//垂直布局
GUILayout.BeginVertical();
GUILayout.Label(info);
GUILayout.EndVertical();
GUILayout.EndArea();
}
}
进入PlayerShooting类里去调用,把信息打印出来
private void ShootServerRpc(string hittedName) {
//输出谁击中了谁
GameManager.UpdateInfo(transform.name + " hit " + hittedName);
}
来陪我,好烦今天。
晚安宝贝早点睡
跑步去
今儿地太湿了