此案例完成了在局域网的多人对战,,,下面是实现过程,,,
1,创建空物体添加Network Manager 和 NetworkManagerHUD组件:
运行游戏场景就可以看到,,如下图:
2,创建PlayerPrefab,,,(自定义主角),,然后添加组件Network Identity(勾选die日哥复选框,Local Player Authority),并且将创建好的预值体,赋值给Network Manager面板的Spawn Info下的Play Prefab
3,编写PlayerMove脚本控制主角移动,,代码如下:就可以在客户端只控制自己的代码了,,
public class PlayerMove : NetworkBehaviour //更改了继承
{
void Update()
{
if (!isLocalPlayer) //若不是本地的主角则不产生操作
{
return;
}
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
this.transform.Translate(new Vector3(0, 0, -v * Time.deltaTime *10));
this.transform.Rotate(new Vector3(0, h * 6, 0));
}
}
4,同步客户端和服务端的主角位置,,在主角的预制体上添加Network transform,,注意是在Player预制体上添加此组件,,,
5,用颜色区分游戏对象哪个是自己控制的,,,接着上面的代码编写:
//此方法在启动本地角色的时候调用 -- 控制主角场景中显示
public override void OnStartLocalPlayer()
{
GetComponent<MeshRenderer>().material.color = Color.yellow;
}
运行结果:
6,控制主角的射击,,首先创建出子弹预制体,并且添加Rigidboy组件,,在Player预制体下创建一个空物体,用于控制生成子弹的位置,,,然后继续编写上面的代码:
void CmdFire() //在Update中设置条件调用
{
//生成子弹预制体
GameObject go = Instantiate(prefabBill, BillPos.transform.position, BillPos.transform.rotation);
//给子弹初速度
go.GetComponent<Rigidbody>().velocity = -go.transform.forward * 5;
//3秒后销毁预制体
Destroy(go,3f);
}
7,子弹的同步:在子弹预制体上添加组件,NetworkIdentity 组件和 NetworkTransform 组件然后更改同步信息为Rigidboy3D,,,
然后将子弹的预制体添加到NetWork Manager 上,以同步服务端数据:
控制主角和子弹的完整代码:
using UnityEngine;
using UnityEngine.Networking;
public class PlayerMove : NetworkBehaviour
{
public GameObject prefabBill; //子弹的预制体
public Transform BillPos; //子弹生成的位置
void Update()
{
if (!isLocalPlayer) //若不是本地的主角则不产生操作
{
return;
}
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
this.transform.Translate(new Vector3(0, 0, -v * Time.deltaTime *10));
this.transform.Rotate(new Vector3(0, h * 6, 0));
if (Input.GetMouseButtonDown(0))
{
CmdFire();
}
}
//该特性表示在服务端调用此方法,运行是在客户端(同步)
[Command]
void CmdFire() //方法名一定是Cmd开头
{
//子弹的生成需要在Sever端,然后同步到客户端,,
GameObject go = Instantiate(prefabBill, BillPos.transform.position, BillPos.transform.rotation);
go.GetComponent<Rigidbody>().velocity = -go.transform.forward * 5;
Destroy(go,3f);
//生成指定的游戏物体在客户端
NetworkServer.Spawn(go);
}
//启动本地角色的时候调用 -- 控制主角场景中显示
public override void OnStartLocalPlayer()
{
GetComponent<MeshRenderer>().material.color = Color.yellow;
}
}
8,添加血量和进行血量控制:
编写脚本,(给需要血量的游戏物体添加)
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class Health : NetworkBehaviour {
public Slider healehSlider;
//同步变量 从服务端到客户端 (hook = "方法名",,每当此变量发生变化就调用方法)
[SyncVar(hook = "OnChangeHealth")]
public const int maxHealth = 100;
public int curHealth = maxHealth;
public void Damager(int damage)
{
//只在服务端计算血量,,,
if (isServer == false) return;
curHealth -= damage;
if (curHealth <= 0)
{
curHealth = 0;
Debug.Log("TODO DEAD");
}
//控制血条的显示
healehSlider.value = curHealth / (float)maxHealth;
}
/// <summary>
/// 同步到客户端的血量数据
/// </summary>
void OnChangeHealth(int health)
{
healehSlider.value = health / (float)maxHealth;
}
}
给子弹添加碰撞事件,即碰撞到有血量的物体,游戏对象就掉血:
public class Bullet : MonoBehaviour {
private void OnCollisionEnter(Collision collision)
{
GameObject hit = collision.gameObject;
Health health = hit.GetComponent<Health>();
if (health != null)
{
health.Damager(10);
}
Destroy(this.gameObject);
}
}
9,添加血条进行显示血量,,,
创建UGUI下的 Slider,,调整为血条的样子,然后将Canvas调整为Player的子物体,Slider的位置调整到人物的上面,并且叫Canvas的Reader Mode 属性设置为World Space 如下图:
这样发布出来,即可多个人连接起来玩耍了,,,我在这里没有完善死亡后的消失,重生的状态,,基本思路的是死亡销毁,然后随机位置生成,这样就可以完成多人对战了,,,
作者:Czhenya
链接:https://czhenya.blog.csdn.net/article/details/78309812
来源:CSDN
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。