使用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各元件使用将在介绍在下一博文开始介绍 ...
随机推荐
- JSP基础概要
[版权申明:本文系作者原创,转载请注明出处] 文章出处:http://blog.csdn.net/sdksdk0/article/details/51925232 作者:朱培 ID:sdksdk0 一 ...
- Intellij IDEA 插件开发之自建插件仓库
Intellij IDEA 有一个自己的官方的插件仓库,但是当我们的开发的 Intellij IDEA 的插件不能够对外公开时,我们就需要搭建自己的 Intellij IDEA 的插件仓库.前不久我们 ...
- Dynamics CRM Trace Reader for Microsoft Dynamics CRM
CRM中抓取日志的视窗工作叫做Diagnastics Tools For Dyanmics CRM,这个工具我们只是作为一个开关来用就不做多介绍了,日志生成后是个文本文档可读性是很差的,那就需要个视窗 ...
- Solr 5.5.0 + tomcat 7.0.69 + zookeeper-3.4.6 Cloud部署
Solr介绍:Solr是一个独立的企业级搜索应用服务器,Solr基于Lucene的全文搜索服务器,同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置.可扩展并对查询性能进行了 ...
- 1091. Acute Stroke (30)
题目如下: One important factor to identify acute stroke (急性脑卒中) is the volume of the stroke core. Given ...
- 【移动开发】startForeground()让服务保持前台级别
最近在使用android 4.1系统的时候,发现在手机休眠一段时间后(1-2小时),后台运行的服务被强行kill掉,有可能是系统回收内存的一种机制,要想避免这种情况可以通过startForegroun ...
- Cocos2D iOS之旅:如何写一个敲地鼠游戏(一):高清屏显示和UIKit
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...
- 网站开发进阶(四十三)html中,路径前加“/” 与不加“/”的区别
网站开发进阶(四十三)html中,路径前加"/" 与不加"/"的区别 前言 <script src="js/downloadify.js&quo ...
- IOC 控制反转(Inversion of Control,英文缩写为IoC)
在采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑. 在这样的齿轮组中,因为是协同工作,如果有一个齿轮出了问题,就可能会影响到整个齿 ...
- DB Query Analyzer 6.04 is distributed, 78 articles concerned have been published
DB Query Analyzer 6.04 is distributed,78 articles concerned have been published DB Query Analyz ...