您的位置:首页 > 移动开发 > Unity3D

Unity3D手机游戏开发-金玺曾读书摘要(2015-4-27 19:01、2016-4-11 10:39)

2015-10-10 10:02 591 查看
http://web01264.w31.vhost002.cn/downloads/Unity官方公布热更新方案性能对比.pdf

苹果禁止了C#的部分反射操作,禁止JIT(即时编译,程序运行时创建并运行新代码),不允许逻辑热更新,只允许使用AssetBundle
进行资源热更新。
Android应用的热更新
将执行代码预编译为assembly dll。
将代码作为TextAsset打包进Assetbundle。
运行时,使用Reflection机制实现代码的功能。
更新相应的Assetbundle即可实现热更新。

Android与iOS热更新的异同
苹果官方禁止iOS的程序热更新;JIT在iOS下无效。
热更新方案:Unity+Lua插件。
使用Lua插件进行iOS热更新的原理
脚本转化为文本资源(如同纹理、音频等)
Lua脚本可直接解释执行
更新资源的形式更新程序

Unity热更新的注意点
需要更新的代码、资源,都必须打包成AssetBundle(建议使用未压缩的格式打包)
熟悉Unity的几个重要的路径
Resources(只读)
StreamingAssets(只读)
Application.dataPath(只读)
Application.persistentDataPath(可读写)

重要路径之Resources
Resources文件夹下的资源无论使用与否都会被打包
资源会被压缩,转化成二进制
打包后文件夹下的资源只读
无法动态更改,无法做热更新
使用Resources.Load加载

重要路径之StreamingAssets
流数据的缓存目录
文件夹下的资源无论使用与否都会被打包
资源不会被压缩和加密
打包后文件夹下的资源只读,主要存放二进制文件
无法做热更新
WWW类加载(一般用CreateFromFile,若资源是AssetBundle,依据其打包方式看是否是压缩的来决定)
相对路径,具体路径依赖于实际平台
Application.streamingAssetsPath
iOS:Application.dataPath+"/Raw"或Application/xxxxxxxx-xxxx-xxxx-xxxx--xxxxxxxxxxxx/xxx.app/Data/Raw

重要路径之Application.dataPath
游戏的数据文件夹的路径(例如在Editor中的Assets)
很少用到
无法做热更新
iOS路径:
Application/xxxxxxxx-xxxx-xxxx-xxxx--xxxxxxxxxxxx/xxx.app/Data

重要路径之Application.persistentDataPath
持久化数据存储目录的路径(沙盒目录,打包之前不存在)
文件夹下的资源无论使用与否都会被打包
运行时有效,可读写
无内容限制,从StreamingAsset中
读取二进制文件或从AssetBundle读取文件来写入PersistentDataPath中
适合热更新
iOS路径:Application/xxxxxxxx-xxxx-xxxx-xxxx--xxxxxxxxxxxx/Documents

支持Unity iOS热更新的各种Lua插件的对比
uLua(asset store)
uLua插件源生版本,开山鼻祖
不会产生静态代码
反射机制,效率低下,速度慢,gc alloc频繁
已停止更新维护,不支持Unity 5.x,淡出主流
uLua & cstoLua
开发平台成熟稳定,Bug修复迅速
开发者众多,资源丰富
静态方法,性能优
有成功商业产品案例
都是基于原声版本的改进;未来,两者会合并成一个插件
sLua
静态方法,性能优
核心代码简洁
资源较少,开发平台不够成熟稳定
无成功商业产品案例
基于原声版本的改进
C#Light(L#)
淡出主流
uniLua
C#实现的Lua虚拟机,非完整方案
淡出主流

Unity3D手机游戏开发

金玺曾

2013年8月出版

前言

全书通篇以实例为基础

作者 金玺曾

2013年4月11日

chap3第一人称射击游戏

在本章的内容中,将涉及摄像机控制、物理、动画、智能寻路等。

3.1策划

场景中只有一个主角和一种敌人。

3.1.1游戏介绍

在游戏场景中,会有若干个敌人的出生点,它会定时生成一些敌人,它们会寻找并攻击主角,游戏的目的就是生存下去,消灭更多敌人,获取更多分。

3.1.2 UI界面

包括主角的生命值、弹药数量、得分和瞄准星。

游戏失败后提供一个按钮重新开始游戏。

3.1.3主角

我们看不到主角本人,在屏幕上看到的是一支端在胸前的M16机关枪。按键盘的W、S、A、D键控制主角前后左右行动,移动鼠标旋转视角,按鼠标左键进行射击。

3.1.4敌人

敌人只有一种,是一个护士模样的僵尸,它将具有智能寻路功能,躲避障碍物,并攻击主角。

3.2游戏场景

这个场景使用了Lightmap和Light Probe表现静态和动态模型的光影效果。

在菜单栏选择【Component】->【Physics】->【Mesh Collider】为其添加多边形碰撞体组件。

3.3主角

需要为主角创建碰撞体,并控制其移动。

3.3.1角色控制器

在菜单栏选择【GameObject】->【Create Empty】创建一个空的游戏体,将它的Tag设为Player,它便是我们的主角。

在菜单栏选择【Component】->【Physics】->【Character Controller】为主角添加一个角色控制器组件,使用这个组件提供的功能,我们将可以实现在控制主角移动的同时与场景的碰撞产生交互,比如在行走时不会穿到墙里面去。

为主角再添加一个Rigidbody组件,取消选择Use Gravity去掉重力模拟,并选中Is Kinematic使其不受物理演算影响,这样我们才能使用脚本控制其移动。在Character Controller组件中需要调整碰撞体的位置和大小。

3.3.2摄像机

接下来我们将在Player.cs脚本中添加少许代码,使摄像机伴随着主角移动。

3.3.3武器

接下来我们将把武器绑定到摄像机上,使其随着主角移动。

3.4敌人

3.4.1寻路

Unity的寻路系统分为两部分,一部分是对场景进行设置,使其满足寻路算法的需求。另一部分是设置寻路者。

3.4.2设置动画

3.5UI界面

这一次我们将使用另一种方式,直接在场景中创建2D贴图表示UI界面。

3.6交互

3.7出生点

3.8小地图

小结

本章完成了一个完整的第一人称射击游戏实例。

chap4塔防游戏

本章将使用Unity完成一款塔防游戏。我们将在Unity内创建二维数组保存场景信息,自定义路点引导敌人行动,还将涉及摄像机控制,读取XML文件,自定义按钮等。

小结

本章完成了一个塔防游戏的实例,内容较多,我们使用二维数组定义场景中的单元格数据,制作引导敌人行动的路点,并添加一些简单的编辑器功能帮助设置路点。

5.7贴图

对于作为模型材质使用的图片,其大小必须是为2的N次方。通常会将其Texture Type设为默认的Texture类型,将Format设为Compressed模式进行压缩。

如果图片将作为UI使用,需要将Texture Type设为GUI。值得注意的是Format的设置。

5.8 3D模型导出流程

5.8.1 3ds Max静态模型导出

3ds Max是最流行的3D建模、动画软件,可以使用它来完成Unity游戏中的模型或动画,最后将模型或动画导出为FBX格式到Unity中使用。在静态模型(没有动画)制作过程中,可以遵循下列步骤和规范:

步骤08:将导出的模型和贴图复制粘贴到Unity工程路径Assets文件夹内的某个位置即可导入到Unity工程中。

5.8.2 3ds Max动画模型导出

动画模型是指那些绑定了骨骼并可以动画的模型,其模型和动画通常需要分别导出。

5.8.3 3ds Max动画导出

动画文件可以与模型文件分开保存,但动画文件中的骨骼与层级关系一定要与模型文件一致。当导出动画的时候,不需要选择模型,只需要选择骨骼和Helper物体导出即可。

动画文件的命名需要按“模型名@动画名”这样的格式命名,比如模型命名为Player,动画文件即可命名为Player@idle,Player@walk等。

5.8.4 Maya模型导出

Maya也是一款非常流行且功能强大的3D动画软件,它的内部坐标系统与Unity一样都是Y轴向上,非常适合完成Unity游戏的模型工作。

在Maya中完成模型的制作可以遵循下列步骤:

步骤06:选择需要导出的模型,在菜单栏选择File|Export Selection,将导出格式设为FBX,选择Export打开设置窗口。如果不需要导出动画,可以取消选中Animation,然后将Units设为Centimeters,最后按Export导出。

5.9动画

Unity4.0引入了全新的Mecanim动画系统,它提供了更强大的功能,使用一个叫状态机的系统控制动画逻辑,更容易实现动画过渡、IK、动画retargeting(将同一个动画使用到不同的模型上)等功能。使用Mecanim动画系统的基本步骤如下:

步骤01:将从3D动画软件中导出的FBX文件复制到Unity工程中。一个模型可以拥有多个动画,模型与动画一定要有相同的骨骼层级关系。

chap7基于TCP/IP协议的聊天实例

在VS中编译工程,在当前工程的bin目录内会出现一个UnityNetwork.dll文件,我们将把它使用到聊天客户端和服务器端内。

聊天客户端将在Unity中完成。在Unity中有两种方式使用前面完成的网络引擎,一种方法是直接将UnityNetwork.dll复制到Unity工程Assets目录的任何地方,另一种方式是直接将原始代码文件复制到Unity工程内,但需要将namespace去掉。

创建脚本ChatClient.cs,并将其指定给场景中的游戏体。这是一个标准的Unity脚本,它包括一个简单的输入框UI用于输入聊天信息,还包括一个按钮发送聊天信息。

Protobuf除了可以应用到网络中,也可以应用到文件存储中。
http://download.csdn.net/download/wsyzyrxp1/9154163
D:\protoGen\ProtoBufTransForm>protogen -i:PlanetProto.txt -o:BjoyProto.cs

protobuf-net:protogen - code generator for .proto

proto协议

package chat;

message UserChat{

required int32 m_nUserID = 1;

optional string m_strNickName = 2 [default = ""];

required string m_strMessage = 3;

}

包体长度=34-18=16

//package ServerMessage;对应using ServerMessage;
message SignUpResponse

{

optional int32 errorCode = 1;

optional float version = 2;
}

包体长度=5=23-18

message LogonReqMessage{

required int64 acctID = 1;

required string passwd = 2;

}

包体长度=20=38-18

enum UserStatus{

OFFLINE = 0; //表示处于离线状态的用户

ONLINE = 1; //表示处于在线状态的用户

}

message UserInfo{

required int64 acctID = 1;

required string name = 2;

required UserStatus status = 3;

}

包体长度=16=34-18

message LogonRespMessage{

required bool logonResult = 1;

required UserInfo userInfo = 2;

}

包体长度=20=38-18
///注册事件处理方法

PacketManager.Instence.RegistDoProcess (0x1234, OnProcessPacket);

PacketManager.Instence.RegistDoProcess (0x1235, OnProcessPacket1);

PacketManager.Instence.RegistDoProcess (0x1034, OnProcessPacket2);

PacketManager.Instence.RegistDoProcess (0x1134, OnProcessPacket3);

PacketManager.Instence.RegistDoProcess (0x1334, OnProcessPacket4);

///注册解析数据包方法

PacketManager.Instence.RegistParserProcess (0x1234, CDecoder.ProcessParserPacket<chat.UserChat>);

PacketManager.Instence.RegistParserProcess (0x1235, CDecoder.ProcessParserPacket<chat.SignUpResponse>);

PacketManager.Instence.RegistParserProcess (0x1034, CDecoder.ProcessParserPacket<chat.LogonReqMessage>);

PacketManager.Instence.RegistParserProcess (0x1134, CDecoder.ProcessParserPacket<chat.UserInfo>);

PacketManager.Instence.RegistParserProcess (0x1334, CDecoder.ProcessParserPacket<chat.LogonRespMessage>);
//发送数据
DataUnit dataUnit = new DataUnit();

dataUnit.m_nCmd = 0x1234;

dataUnit.m_nChannelID = 1;

chat.UserChat chatmessage = new chat.UserChat();

chatmessage.m_nUserID = 125;

chatmessage.m_strNickName = "client";

chatmessage.m_strMessage = message;

dataUnit.m_oBodyUnit = chatmessage;

SocketManager.Instance.SendDataUnit (dataUnit);
DataUnit dataUnit1 = new DataUnit();

dataUnit1.m_nCmd = 0x1235;

dataUnit1.m_nChannelID = 1;

chat.SignUpResponse req = new chat.SignUpResponse();

req.errorCode = 0;

req.version = 1;

dataUnit1.m_oBodyUnit = req;

SocketManager.Instance.SendDataUnit (dataUnit1);
System.IO.MemoryStream ms = new System.IO.MemoryStream();

ProtoBuf.Serializer.Serialize<chat.SignUpResponse>(ms,req);

byte[] result = ms.ToArray();

ms.Close();

UnityEngine.Debug.LogError("长度:"+ result.Length);

DataUnit dataUnit1 = new DataUnit();

dataUnit1.m_nCmd = 0x1034;

dataUnit1.m_nChannelID = 1;

chat.LogonReqMessage req = new chat.LogonReqMessage();

req.acctID = 4294967296;

req.passwd = "Bjoy29438253";

dataUnit1.m_oBodyUnit = req;

SocketManager.Instance.SendDataUnit (dataUnit1);
System.IO.MemoryStream ms = new System.IO.MemoryStream();

ProtoBuf.Serializer.Serialize<chat.LogonReqMessage>(ms,req);

byte[] result = ms.ToArray();

ms.Close();

UnityEngine.Debug.LogError("长度:"+ result.Length);

DataUnit dataUnit1 = new DataUnit();

dataUnit1.m_nCmd = 0x1134;

dataUnit1.m_nChannelID = 1;

chat.UserInfo req = new chat.UserInfo();

req.acctID = 4294967296;

req.name = "hxh韩";

req.status = chat.UserStatus.ONLINE;

dataUnit1.m_oBodyUnit = req;

SocketManager.Instance.SendDataUnit (dataUnit1);
System.IO.MemoryStream ms = new System.IO.MemoryStream();

ProtoBuf.Serializer.Serialize<chat.UserInfo>(ms,req);

byte[] result = ms.ToArray();

ms.Close();

UnityEngine.Debug.LogError("长度:"+ result.Length);

DataUnit dataUnit1 = new DataUnit();

dataUnit1.m_nCmd = 0x1334;

dataUnit1.m_nChannelID = 1;

chat.LogonRespMessage req = new chat.LogonRespMessage();

req.logonResult = true;

chat.UserInfo req1 = new chat.UserInfo();

req1.acctID = 4294967296;

req1.name = "hxh韩";

req1.status = chat.UserStatus.ONLINE;

req.userInfo = req1;

dataUnit1.m_oBodyUnit = req;

SocketManager.Instance.SendDataUnit (dataUnit1);
System.IO.MemoryStream ms = new System.IO.MemoryStream();

ProtoBuf.Serializer.Serialize<chat.LogonRespMessage>(ms,req);

byte[] result = ms.ToArray();

ms.Close();

UnityEngine.Debug.LogError("长度:"+ result.Length);

//接收数据

public static int i = 0;

public System.Text.StringBuilder m_content = new System.Text.StringBuilder();

public int OnProcessPacket(DataUnit dataUnit)

{

UnityEngine.Debug.LogError("OnProcessPacket"+dataUnit.m_nCmd);

if (dataUnit.m_oBodyUnit != null) {

if(dataUnit.m_oBodyUnit.GetType() == typeof( chat.UserChat ) )

{
chat.UserChat chatMessage = (chat.UserChat)dataUnit.m_oBodyUnit;

m_content.Length=0;

m_content.Append(string.Format("echo {0} : {1}{2}", chatMessage.m_strNickName, chatMessage.m_strMessage, i++));

UnityEngine.Debug.LogError(m_content.ToString());

}

}
return 0;

}
public int OnProcessPacket1(DataUnit dataUnit)

{

UnityEngine.Debug.LogError("OnProcessPacket1"+dataUnit.m_nCmd);

if (dataUnit.m_oBodyUnit != null) {

if(dataUnit.m_oBodyUnit.GetType() == typeof( chat.SignUpResponse ) )

{

UnityEngine.Debug.LogError("OnProcessPacket1---SignUpResponse");

chat.SignUpResponse chatMessage = (chat.SignUpResponse)dataUnit.m_oBodyUnit;

m_content.Length=0;

m_content.Append(string.Format("echo {0} : {1}{2}", chatMessage.errorCode, chatMessage.version, i++));

UnityEngine.Debug.LogError(m_content.ToString());

}

}

return 0;

}

public int OnProcessPacket2(DataUnit dataUnit)

{

UnityEngine.Debug.LogError("OnProcessPacket2"+dataUnit.m_nCmd);

if (dataUnit.m_oBodyUnit != null) {

if(dataUnit.m_oBodyUnit.GetType() == typeof( chat.LogonReqMessage) )

{

UnityEngine.Debug.LogError("OnProcessPacket2---LogonReqMessage");

chat.LogonReqMessage chatMessage = (chat.LogonReqMessage)dataUnit.m_oBodyUnit;

m_content.Length=0;

m_content.Append(string.Format("echo {0} : {1}{2}", chatMessage.acctID, chatMessage.passwd, i++));

UnityEngine.Debug.LogError(m_content.ToString());

}

}

return 0;

}

public int OnProcessPacket3(DataUnit dataUnit)

{

UnityEngine.Debug.LogError("OnProcessPacket3"+dataUnit.m_nCmd);

if (dataUnit.m_oBodyUnit != null) {

if(dataUnit.m_oBodyUnit.GetType() == typeof( chat.UserInfo) )

{

UnityEngine.Debug.LogError("OnProcessPacket3---UserInfo");

chat.UserInfo chatMessage = (chat.UserInfo)dataUnit.m_oBodyUnit;

m_content.Length=0;

m_content.Append(string.Format("echo {0} : {1}: {2}", chatMessage.acctID, chatMessage.name, chatMessage.status));

UnityEngine.Debug.LogError(m_content.ToString());

}

}

return 0;

}

public int OnProcessPacket4(DataUnit dataUnit)

{

UnityEngine.Debug.LogError("OnProcessPacket4"+dataUnit.m_nCmd);

if (dataUnit.m_oBodyUnit != null) {

if(dataUnit.m_oBodyUnit.GetType() == typeof( chat.LogonRespMessage) )

{

UnityEngine.Debug.LogError("OnProcessPacket4---LogonRespMessage");

chat.LogonRespMessage chatMessage = (chat.LogonRespMessage)dataUnit.m_oBodyUnit;

m_content.Length=0;

m_content.Append(string.Format("echo {0} : {1}: {2}: {3}", chatMessage.logonResult,chatMessage.userInfo.acctID, chatMessage.userInfo.name, chatMessage.userInfo.status));

UnityEngine.Debug.LogError(m_content.ToString());

}

}

return 0;

}
chap9将Unity游戏移植到iOS平台

9.1 iOS简介

iOS主要安装在iPhone和iPad设备上面。

开发iOS游戏或应用,首先需要到苹果公司的官方网站申请iOS开发权限,理论上只能在苹果公司的Mac计算机上开发。

iOS游戏可以发布到苹果公司的App Store中,这是发布iOS游戏的唯一合法途径。

使用Unity开发iOS游戏并不需要对Objective-C有非常深入的了解。

9.2软件安装

开发iOS游戏,首先要准备一台Mac计算机,然后到苹果公司开发者网站或Mac电脑上的App Store中免费下载Xcode软件,将其安装到Mac上。

Xcode是开发苹果软件的必备工具,最新版只支持Lion操作系统,而Snow Leopard操作系统,要下载对应的老版本。

安装好Xcode后,再安装Mac版的Unity,在Mac上安装Unity的过程与PC版基本一样。

9.3申请开发权限

9.4设置iOS开发环境

9.5测试iOS游戏

9.6发布iOS游戏

9.6.1申请发布证书

发布游戏需要申请一个用于发布的证书(之前申请的是用于测试的证书),这个证书只需要申请一次,将来可以反复使用。

chap10将Unity游戏移植到Android平台

启动Unity,在菜单栏选择Edit|Preferences|External Tools|Android SDK Location指定Android SDK的位置。

在Unity中可以直接使用Java库文件,其格式为.jar。

附录A C#语言

Unity使用的C#和微软.NET平台下的C#很像但又不完全一样。Unity内的C#运行于Mono虚拟机,它是一个开源软件平台。

值类型包括内置类型,结构和枚举。

引用类型包括类和委托。

与C++的预处理相比,C#的预处理不支持宏。

C#提供了垃圾回收器,在程序执行到对象的作用域以外时,对象会自动被系统垃圾回收,因此不需要显示地通过delete销毁。

在Unity中,继承自MonoBehaviour的类不能使用new创建,同时也不能使用构造函数。

C#使用访问修饰符pubilc、protected、internal、protected internal、private决定类或类成员的可见性,尽可能封装内部实现。

pubilc,完全公开,可以在类内部或外部任何地方访问

protected,同一名字空间内的派生类可以访问

internal,同一名字空间内的任何地方可以访问

protected internal,满足protected或internal的条件可以访问

private,仅在类内部可以访问

在当前版本的Unity中,C#并不支持名字空间。

所有C#类都是从System.Object派生出来的。

C#的委托支持泛型参数,也就是委托可以对应任何类型的参数列表。

附录B 特殊文件夹

ActionScript

存放Flash的ActionScript脚本。当游戏被导出为Flash格式的时候,这里的脚本会自动替换指定的C#脚本。

Editor

存放编辑器脚本

Gizmos

通常是存放TIF格式的图片,在OnDrawGizmos函数内使用Gizmos.DrawIcon将其画为图标在场景中显示。

Plugins/iOS

存放iOS插件,包括.a或.m、.mm文件等。

Resources

存放使用Resources.Load()动态读取的资源,它们可以是图片、模型等不同类型的资源。

Standard Assets

标准Unity资源包

StreamingAssets

独立存放到文件系统中媒体文件,如视频等。

WebPlayerTemplates

存放网页游戏模板,其中的每个模板均以一个自定义名称的子目录形式存放。

Unity3D V3.0中文快速入门教程
http://www.docin.com/p-290465538.html
Unity3D的基本界面介绍

场景面板:

动画面板Game:是用来渲染场景面板中景象的。该面板不能用作编辑,但却可以呈现完整的动画效果。

层次清单栏Hierarchy:

项目文件栏:

对象属性栏:

场景调整工具:
菜单栏中包含有8个菜单选项:

文件

编辑

资源

游戏对象

组件

地形

窗口

帮助

其各自又有自己的子菜单。

Assets|Create|JavaScript

初始化函数

function Start(){

print("Game is start");

将这段代码拖拽给层次清单栏中任意一个对象,则在左下方的控制台面板中看到这句话。

刷帧函数

function Update(){

print(Time.time);

}

显示游戏开始到现在所消耗的时间值。

var AddSpeed=5;

function Update(){

transform.Translate(0,0,AddSpeed);

}

该代码为对象添加了一个在Z方向上的初始速度,如果在没有其他外力的作用下,物体将一直沿着Z方向以5的速度行驶。并且当您将这段代码拖拽给一个物体对象之后,它的这个初始速度可以作为一个接口在它的属性面板中进行修改。

除了数字作为接口之外,接口还可以是对象。

//定义一个变换对象cubeGO

var cubeGO:Transform;
//一旦按下G键

if(Input.GetKey(KeyCode.G)){

cubeGO.Transform(0,0,AddSpeed);

}

在菜单栏中选中File|Build Settings或者按下Ctrl+Shift+B键的组合来发布工程文件。

我简单介绍一下这个面板:

Scenes In Build:要发布的场景文件列表。后面的数值是场景的加载顺序,0为最先被加载的主场景文件。

Platform:导出的文件格式。如果您没有购买正式的U3D专业版软件,那么您只能发布前两种格式的文件。如果您已经购买了U3D专业版软件,那么您还得注意第四种iOS格式的文件,必须在苹果的Mac OS X操作系统下才能发布。

在start场景中的画面,完全由GUI代码绘制而成,所以在您未对项目运行的时候,Game动画面板中将不会显示任何东西。

10.3运行Android游戏

10.3.1设置Android手机

准备一部手机,CPU最好是ARMv7架构的。

Portrait表示竖屏,Landscape表示横屏。选择Auto Rotation可以自动旋转屏幕方向。

4种大小的图标,分别是96*96,72*72,48*48,36*36。

默认启动Unity游戏的时候将会看到Unity的Logo,在Splash Image中指定一张图片即可替换默认的启动画面,在Splash scaling中可以设置启动图片的缩放。

Bundle Identifier是游戏的标识。在Minimum API Level中设置游戏所支持的最小API版本。

在Device Filter中只有ARMv7 only选项。

在Install Location中提供了几种游戏安装方式,Prefer External会将游戏安装到外部存储卡中。

10.4触屏操作

鼠标操作无法实现一些特有的触屏操作,比如多点触屏。

UNITY_EDITOR、UNITY_iOS、UNITY_ANDROID是Unity预设的预处理标识符。

10.5.1从eclipse到Unity

与iOS平台一样,理论上可以使用Unity完成一款Android游戏且不写一行Android平台相关代码,但如果我们需要调用Android平台专有的API,那么就不得 不接触一些Android平台相关的东西。


使用Unity创建塔防游戏2016-3-30 16:00

Unity3d学习笔记(五)--结合Mecanim实现怪物AI
/article/8309582.html

Unity3D开发(五):Unity3D 4.x 使用Mecanim实现连击
/article/1385577.html

MeatEgg
怪物动画状态机
Project_txl/Animations/Roudan_AnimatorController.controller
Base Layer
Default state:XiaLuo
XiaLuo->Jump->Move
这里只用3个动作描述,下落状态(XiaLuo),跳跃状态(Jump),移动状态(Move)
// 使用字符串变量保存当前状态,避免多处引用写错
private static readonly string XiaLuoState = "Base Layer.XiaLuo";
private static readonly string JumpState = "Base Layer.Jump";
private static readonly string MoveState = "Base Layer.Move";
MeatEggAI.cs
在Start()中获取Animator组件引用
/// <summary>
/// 动画组件
/// </summary>
private Animator m_animator;
m_animator = this.GetComponent<Animator>();
在Update()中根据当前状态和输入参数促使状态切换

private Vector3 targetPos;

AnimatorStateInfo stateInfo = this.animator.GetCurrentAnimatorStateInfo(0);
if (stateInfo.nameHash == Animator.StringToHash(XiaLuoState) && !m_animator.IsInTransition(0))
{
m_animator.SetBool("XiaLuo", false);
m_animator.SetBool("Jump", true);
m_transform.eulerAngles = new Vector3(0, Random.Range(0,360), 0);
}

if (stateInfo.nameHash == Animator.StringToHash(JumpState) && !m_animator.IsInTransition(0))
{

m_animator.SetBool("Jump", false);
m_animator.SetBool("Move", true);
……
}

if (stateInfo.nameHash == Animator.StringToHash(MoveState))
{

……

RotateTo(targetPos);
m_transform.Translate(0, 0, 3.0f * Time.deltaTime);
}

C#脚本命名为MonsterManager.cs【MonsterData】

在MonsterManager类中定义一个MonsterPref类型【MonsterLevel】:
[System.Serializable]
public class MonsterPref
{
/// <summary>
/// 怪物名称
/// </summary>
public string name;
/// <summary>
/// 怪物类型
/// </summary>
public Monster.MonsterType type;
/// <summary>
/// 怪物预制
/// </summary>
public Monster prefab;

}
我们添加了[System.Serializable]这个特性来使这个类的对象可以在监视面板中编辑。这可以使我们方便快速的改变MonsterPref中的值。
我们将预先定义的MonsterPref存储在数组MonsterPref []或List<T>中。
public MonsterPref[] monsterPrefabs;
public MonsterPref bonusPrefab;






内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: