使用Multiplayer Networking做一个简单的多人游戏例子-3/3(Unity3D开发之二十七)
使用Multiplayer Networking做一个简单的多人游戏例子-1/3
使用Multiplayer Networking做一个简单的多人游戏例子-2/3
使用Multiplayer Networking做一个简单的多人游戏例子-3/3
上一篇中血条还没有同步到所有客户端,下面添加血条同步。主要用到[SyncVar]同步变量。
13. 网络同步血条
- 打开Health脚本
- 添加命名空间UnityEngine.Networking
using UnityEngine.Networking;
- 添加继承关系为NetworkBehaviour
public class Health : NetworkBehaviour
- 为currentHealth添加[SyncVar]
[SyncVar]
public int currentHealth = maxHealth;
- 在TakeDamage函数中增加仅在Server端执行
if (!isServer)
{
return;
}
最终Health脚本如下:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Collections;
public class Health : NetworkBehaviour {
public const int maxHealth = 100;
[SyncVar]
public int currentHealth = maxHealth;
public RectTransform healthBar;
public void TakeDamage(int amount)
{
if (!isServer)
{
return;
}
currentHealth -= amount;
if (currentHealth <= 0)
{
currentHealth = 0;
Debug.Log("Dead!");
}
healthBar.sizeDelta = new Vector2(currentHealth, healthBar.sizeDelta.y);
}
}
此时运行测试,你会发现只有客户端的血条会变化,所以我们需要修改血条变化方法
- 打开Health脚本
- 将血条修改的代码移到新函数OnChangeHealth中
void OnChangeHealth (int currentHealth)
{
healthBar.sizeDelta = new Vector2(health, currentHealth.sizeDelta.y);
}
- 修改currentHealth的SyncVar属性
[SyncVar(hook = "OnChangeHealth")]
最终Health代码:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Collections;
public class Health : NetworkBehaviour {
public const int maxHealth = 100;
[SyncVar(hook = "OnChangeHealth")]
public int currentHealth = maxHealth;
public RectTransform healthBar;
public void TakeDamage(int amount)
{
if (!isServer)
return;
currentHealth -= amount;
if (currentHealth <= 0)
{
currentHealth = 0;
Debug.Log("Dead!");
}
}
void OnChangeHealth (int health)
{
healthBar.sizeDelta = new Vector2(health, healthBar.sizeDelta.y);
}
}
14. 死亡和再出生
这里会用到[ClientRpc],让函数在服务端调用,执行却在客户端
- 打开Health脚本
- 添加出生函数Respawn
[ClientRpc]
void RpcRespawn()
{
if (isLocalPlayer)
{
// move back to zero location
transform.position = Vector3.zero;
}
}
- 修改TakeDamage函数中,currentHealth = maxHealth;
- 在服务端执行RpcRespawn();
最终Health代码如下:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Collections;
public class Health : NetworkBehaviour {
public const int maxHealth = 100;
[SyncVar(hook = "OnChangeHealth")]
public int currentHealth = maxHealth;
public RectTransform healthBar;
public void TakeDamage(int amount)
{
if (!isServer)
return;
currentHealth -= amount;
if (currentHealth <= 0)
{
currentHealth = maxHealth;
// called on the Server, but invoked on the Clients
RpcRespawn();
}
}
void OnChangeHealth (int currentHealth )
{
healthBar.sizeDelta = new Vector2(currentHealth , healthBar.sizeDelta.y);
}
[ClientRpc]
void RpcRespawn()
{
if (isLocalPlayer)
{
// move back to zero location
transform.position = Vector3.zero;
}
}
}
- 保存脚本
- Build新版本,测试
15. 增加敌人
增加敌人发射器用于创建系统玩家
- 创建一个empty GameObject
- 修改名称为“Enemy Spawner”
- 保持Enemy Spawner选中
- 添加组件Network > NetworkIdentity
- 勾选NetworkIdentity中the Server Only选中,仅在服务端中执行
- 给Enemy Spawner添加新脚本“EnemySpawner”
EnemySpawner内容如下:
using UnityEngine;
using UnityEngine.Networking;
public class EnemySpawner : NetworkBehaviour {
public GameObject enemyPrefab;
public int numberOfEnemies;
public override void OnStartServer()
{
for (int i=0; i < numberOfEnemies; i++)
{
var spawnPosition = new Vector3(
Random.Range(-8.0f, 8.0f),
0.0f,
Random.Range(-8.0f, 8.0f));
var spawnRotation = Quaternion.Euler(
0.0f,
Random.Range(0,180),
0.0f);
var enemy = (GameObject)Instantiate(enemyPrefab, spawnPosition, spawnRotation);
NetworkServer.Spawn(enemy);
}
}
}
- 保存脚本
- 回到Unity
下面开始利用Player Prefab创建Enemy
- 将Player prefab拖到场景中
- 修改Player名称为“Enemy”
- 将Enemy拖到Project面板中创建一个新的Enemy prefab预制体
- 选中Enemy
- 删除Enemy中的Gun,点击继续
- 选中Enemy
- 删除Bullet Spawn
- 移除PlayerController组件
- 修改Enemy材质为Black Material
- 修改Enemy Visor的材质为Default-Material
- Apply Enemy Prefab
- 删除场景中的Enemy Prefab
- 保存场景
将 Enemy prefab 注册到NetworkManager中
- 选中NetworkManager
- 展开Spawn Info foldout
- Registered Spawnable Prefabs点击+号
- 将Enemy prefab添加到Registered Spawnable Prefabs list
- 选中场景中的Enemy Spawner
- 将Enemy prefab拖到Enemy prefab输入框中
- 设置Number Of Enemies为4
- 保存工程
build新版本,测试
16. 销毁死亡Enemy
- 打开Health脚本
- 添加destroyOnDeath变量
- TakeDamage中判断销毁或者respawning
代码如下:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Collections;
public class Health : NetworkBehaviour {
public const int maxHealth = 100;
public bool destroyOnDeath;
[SyncVar(hook = "OnChangeHealth")]
public int currentHealth = maxHealth;
public RectTransform healthBar;
public void TakeDamage(int amount)
{
if (!isServer)
return;
currentHealth -= amount;
if (currentHealth <= 0)
{
if (destroyOnDeath)
{
Destroy(gameObject);
}
else
{
currentHealth = maxHealth;
// called on the Server, will be invoked on the Clients
RpcRespawn();
}
}
}
void OnChangeHealth (int currentHealth)
{
healthBar.sizeDelta = new Vector2(currentHealth, healthBar.sizeDelta.y);
}
[ClientRpc]
void RpcRespawn()
{ if (isLocalPlayer)
{
// Set the player’s position to origin
transform.position = Vector3.zero;
}
}
}
- 保存脚本,回到Unity
- 选中Enemy prefab
- 将Health中Destroy On Death 属性勾选
增加出身点位置
由于Player每次出生位置一样,我们用NetworkStartPosition来增加一个出身点
- 创建一个empty GameObject
- 修改名称为“Spawn Position 1”
- 选中Spawn Position 1
- 增加组件Network > NetworkStartPosition
- 设置Transform Position (3, 0, 0)
- 复制一份Spawn Position 1 GameObject
- 将复制这份修改名称为“Spawn Position 2”
- 选中Spawn Position 2
- 设置Transform Position (-3, 0, 0)
- 选中Network Manager
- 展开Spawn Info foldout
- 修改Player Spawn Method 为 Round Robin
设置出生点位置
- 打开Health脚本
- 增加NetworkStartPosition变量
private NetworkStartPosition[] spawnPoints;
- 增加Start方法
void Start ()
{
if (isLocalPlayer)
{
spawnPoints = FindObjectsOfType<NetworkStartPosition>();
}
}
- 修改RpcRespawn中出生点坐标
最终Health代码如下:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Collections;
public class Health : NetworkBehaviour {
public const int maxHealth = 100;
public bool destroyOnDeath;
[SyncVar(hook = "OnChangeHealth")]
public int currentHealth = maxHealth;
public RectTransform healthBar;
private NetworkStartPosition[] spawnPoints;
void Start ()
{
if (isLocalPlayer)
{
spawnPoints = FindObjectsOfType<NetworkStartPosition>();
}
}
public void TakeDamage(int amount)
{
if (!isServer)
return;
currentHealth -= amount;
if (currentHealth <= 0)
{
if (destroyOnDeath)
{
Destroy(gameObject);
}
else
{
currentHealth = maxHealth;
// called on the Server, invoked on the Clients
RpcRespawn();
}
}
}
void OnChangeHealth (int currentHealth )
{
healthBar.sizeDelta = new Vector2(currentHealth , healthBar.sizeDelta.y);
}
[ClientRpc]
void RpcRespawn()
{
if (isLocalPlayer)
{
// Set the spawn point to origin as a default value
Vector3 spawnPoint = Vector3.zero;
// If there is a spawn point array and the array is not empty, pick one at random
if (spawnPoints != null && spawnPoints.Length > 0)
{
spawnPoint = spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position;
}
// Set the player’s position to the chosen spawn point
transform.position = spawnPoint;
}
}
}
Download sample code on github
OK,以上就是全部内容。关于详细的使用请看 Networking Overview
使用Multiplayer Networking做一个简单的多人游戏例子-3/3(Unity3D开发之二十七)的更多相关文章
- 使用Multiplayer Networking做一个简单的多人游戏例子-2/3(Unity3D开发之二十六)
猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/51007512 ...
- 使用Multiplayer Networking做一个简单的多人游戏例子-1/3(Unity3D开发之二十五)
猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/51006463 ...
- 使用Multiplayer Networking做一个简单的多人游戏例子-1/2
原文地址: http://blog.csdn.net/cocos2der/article/details/51006463 本文主要讲述了如何使用Multiplayer Networking开发多人游 ...
- 使用Multiplayer Networking做一个简单的多人游戏例子-1/2(换一种方法)
SynMove.cs using UnityEngine; using System.Collections; using UnityEngine.Networking; public class S ...
- 【Bugly干货分享】一起用 HTML5 Canvas 做一个简单又骚气的粒子引擎
Bugly 技术干货系列内容主要涉及移动开发方向,是由Bugly邀请腾讯内部各位技术大咖,通过日常工作经验的总结以及感悟撰写而成,内容均属原创,转载请标明出处. 前言 好吧,说是“粒子引擎”还是大言不 ...
- 使用React并做一个简单的to-do-list
1. 前言 说到React,我从一年之前就开始试着了解并且看了相关的入门教程,而且还买过一本<React:引领未来的用户界面开发框架 >拜读.React的轻量组件化的思想及其virtual ...
- 【 D3.js 入门系列 --- 3 】 做一个简单的图表!
前面说了几节,都是对文字进行处理,这一节中将用 D3.js 做一个简单的柱形图. 做柱形图有很多种方法,比如用 HTML 的 div 标签,或用 svg . 推荐用 SVG 来做各种图形.SVG 意为 ...
- 一起用HTML5 canvas做一个简单又骚气的粒子引擎
前言 好吧,说是"粒子引擎"还是大言不惭而标题党了,离真正的粒子引擎还有点远.废话少说,先看demo 本文将教会你做一个简单的canvas粒子制造器(下称引擎). 世界观 这个简单 ...
- Jmeter初步使用二--使用jmeter做一个简单的性能测试
经过上一次的初步使用,我们懂得了Jmeter的安装与初步使用的方法.现在,我们使用Jmeter做一个简单的性能测试.该次测试,提交的参数不做参数化处理,Jmeter各元件使用将在介绍在下一博文开始介绍 ...
随机推荐
- Python 3 智能发音
真是十分神奇.. import win32com.client import time s = win32com.client.Dispatch("SAPI.SpVoice") s ...
- pipeline(管道)设计模式
- 2.关于QT中数据库操作,简单数据库连接操作,数据库的增删改查,QSqlTableModel和QTableView,事务操作,关于QItemDelegate 代理
Linux下的qt安装,命令时:sudoapt-get install qt-sdk 安装mysql数据库,安装方法参考博客:http://blog.csdn.net/tototuzuoquan ...
- Dynamics CRM2011 MspInstallAction failed when installing an Update Rollup
今天在给客户做环境迁移,安装包完成后按惯例打补丁,但在打补丁的时候却报错了,错误如下 最开始怀疑第一个打6是不是不对,毕竟N久没碰2011了忘的差不多了,后来下了个rollup1居然也打不上,根据这个 ...
- Dynamics CRM2015 The plug-in type does not exist in the specified assembly问题的解决方法
在用插件工具PluginProfiler调试时,报"The plug-in type xxxx does not exist in the specified assembly" ...
- Android简易实战教程--第十一话《获取手机所有应用信息Engine类详解》
如果想要获取系统手机应用的详细信息,那么下边代码可以直接作为模板使用.笔者对每一行代码都做了注解,供您参考.直接上代码: package com.example.itydl.engines; impo ...
- tomcat集群的failover机制
集群要提供高可用性就必须要有某种机制去保证,常用的机制为failover(故障转移),简单说就是通过一定的heartbeat检测是否有故障,一旦故障发生备份节点则接管故障节点的工作. tomcat使用 ...
- Android性能优化之Splash页应该这样设计
目前SplashActivity的设计 目前市场上的应用在启动时基本上都会先启动一个SplashActivity,作为一个欢迎界面,为什么这样设计呢? 个人总结有三个优点: 1.可以给用户更好的体验 ...
- A*寻路算法入门(六)
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...
- 关于js校验,检验常见的比如:电话,数字,邮箱,手机号等等
/** 验证数字:^[0-9]*$ 验证n位的数字:^\d{n}$ 验证至少n位数字:^\d{n,}$ 验证m-n位的数字:^\d{m,n}$ 验证零和非零开头的数字:^(0|[1-9 ...