unet多人联机
首先添加两个组件
Paste_Image.png
运行后我们可以发现大致的联机已经完成
Paste_Image.png
多人联机我们在玩家游戏对象上添加两个组件。
Paste_Image.png
玩家移动
然后我们再添加一个移动的脚本,写入代码。
using UnityEngine.Networking;
public class PleyerController : NetworkBehaviour {
// Update is called once per frame
void Update () {
if (isLocalPlayer==false) {//如果不是本地的
return;//不执行移动的代码
}
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
transform.Rotate(Vector3.up*h*120*Time.deltaTime);
transform.Translate(-Vector3.forward * v * 3 * Time.deltaTime);
}
最后我们打包出来测试下,我们把Unity当作服务器和客户端,把打包出来的当做客户端.我们可以发现这样就已经连接上了。因为都是本地IP所以没有设置IP地址。端口号是系统默认的端口7777。
Paste_Image.png
区分敌我
下面我们再来看看怎么区分敌我,附上代码
// <summary>
/// 这个方法区分敌我,自身玩家设置为蓝色,敌人是白色.
/// </summary>
public override void OnStartLocalPlayer()
{
//这个方法只会在本地角色那里调用,当角色被创建的时候
GetComponent<MeshRenderer>().material.color = Color.blue;
}
Paste_Image.png
发射子弹
首先我们在子弹的预制物上加上Network Identity组件,并且将生成的子弹上传到网络上。
Paste_Image.png
下面我们来让我们的游戏对象拥有射击功能,看看怎么做吧,先附上射击的代码。这个CmdFire()方法我们在玩家Player预制物的Update里面调用
public GameObject BulletPrefab;
public Transform bulletSpawe;
private float BulltSpeed = 2000f;
[Command]//表示虽然客户端调用这个方法,但是运行是在服务端运行.
void CmdFire()
{//命名必须Cmd开头
GameObject bullet = Instantiate(BulletPrefab, bulletSpawe.position, bulletSpawe.rotation);
bullet.GetComponent<Rigidbody>().velocity = -bullet.transform.forward * BulltSpeed * Time.deltaTime;
Destroy(bullet, 2f);
NetworkServer.Spawn(bullet);//生成指定的物体同步到各个客户端
}
随后我们又发现子弹是同步了,但是子弹的速度没有同步过来,So我们将NetworkTransform组件也加上来,NetworkTransform不仅能同步Transform还能同步Rigibody.
Paste_Image.png
这下我们可以发现子弹都已经同步上了。
Paste_Image.png
控制UI血量值同步
当你添加血量减少受到伤害的方法后你会发现服务端和客户端的血量值并不是同步的,那么是为什么呢,这是因为服务器端在发射子弹后敌人的血量在减少同时子弹也被销毁了,那么客户端就有可能无法同时受到伤害因为在服务器端子弹已经被销毁了,那么我们如何去实现同步能,这里我们只能让子弹伤害在服务端去运行然后在同步到所有的客户端。下面我们附上代码.将这个血量的脚本挂载在Player游戏对象上.
using UnityEngine.Networking;
public class Health : NetworkBehaviour {
public Slider HealthSlider;
public const int MaxHealth = 100;
[SyncVar (hook ="OnChangeHealth")]//同步变量,表示这个变量同步到各个客户端
public int curentllealth = MaxHealth;
//血量减少的方法,受到伤害
public void TakeDamage(int damage) {
if (isServer == false) return;//血量的处理只在服务器端执行
curentllealth -= damage;
if (curentllealth<=0) {
curentllealth = 0;
Debug.Log("Death");
}
}
void OnChangeHealth(int health) {
HealthSlider.value = health / (float)MaxHealth;
}
}
然后我们在创建一个脚本这个脚本挂载在我们的子弹上,里面写入它的碰撞方法。
public class Bullet : MonoBehaviour {
private void OnCollisionEnter(Collision collision)
{
if (collision.transform.tag=="Player") {
GameObject hit = collision.gameObject;
Health health = hit.GetComponent<Health>();
if(health!=null){
health.TakeDamage(20);
}
Destroy(this.gameObject);
}
}
}
这样我们就同步了血量伤害的减少
Paste_Image.png
重生到随机的某几个位置
首先我们先随便创建一个位置点空物体。在其上面添加组件Network Start Position。这个是在服务器开始的时候指定一个位置,然后我们在多创建一个位置同意添加这个组件。让我们的玩家在这两个位置随机生成。
Paste_Image.png
然后我们将Player Spawn Met的参数设置为Round Robin指轮流在这两个位置转换.
Paste_Image.png 然后我们在血量的脚本上附上代码
private NetworkStartPosition[] SpawnPosition;
void Start() {
if (isLocalPlayer) {
SpawnPosition = FindObjectsOfType<NetworkStartPosition>();
}
}
//重生
[ClientRpc]//客户端远程调用
void Rpcespawn() {//命名必须Rpc开头
if (isLocalPlayer==false) {
return;
}
Vector3 spawnposition = Vector3.zero;
if (SpawnPosition!=null&& SpawnPosition.Length>0) {
spawnposition = SpawnPosition[Random.Range(0, SpawnPosition.Length)].transform.position;
}
transform.position = spawnposition;
}
然后我们将重生的方法调用到血量小于等于0的时候
Paste_Image.png
敌人的随机生成
using UnityEngine.Networking;
public class EnumSpwen : NetworkBehaviour {
public GameObject Onemyprefab;
public int numberOfEnemies;
//会在服务器启动的时候调用
public override void OnStartServer()
{
for (int i=0;i< numberOfEnemies;i++) {
Vector3 position = new Vector3(Random.Range(-6f, 6f), 0f,Random.Range(-6f,6f));
Quaternion rotation = Quaternion.Euler(0, Random.Range(0, 360), 0);
GameObject enemy = Instantiate(Onemyprefab,position,rotation);
NetworkServer.Spawn(enemy);
}
}
Paste_Image.png