Archive for the ‘Unity3D’ Category

Unity WebPlayer之间调用JS Post方法传参

星期六, 五月 24th, 2014 6 views

首先是功能需求的描述:我们需要在两个WebPlayer之间互相传递参数,其方法是在WebA中的Unity调用一个JS方法将参数进行一个post提交并跳转到WebB中,并在WebB的Unity中获取这个post的内容。
以上方案涉及到几个内容:
i 在Unity中调用Html中的JS方法并传参
ii Js的Post方法
iii Unity获取当前页面中的post内容
下面将逐一讲解:

①在Unity中调用Html中的JS方法并传参
代码如下
Unity中:

1
2
3
void Start () {
                Application.ExternalCall( "testFunction", "testMessage");
}

这里的testFunction是JS中的函数名,testMessage是我们传递的字符串内容,JS代码这样设计

1
2
3
4
5
function testFunction( arg )
{
    // show the message
    alert( arg );
}

此时将Unity打包成WebPlayer,命名为WebA.html,运行效果如下:

(更多…)

Protobuf-net在Unity中的序列化与反序列化

星期日, 五月 18th, 2014 17 views

本篇中我们只讲解如何在Unity中对Protobuf-net进行序列化(Serialize)与反序列化(Deserialize),关于Unity的socket网络通信部分我们后续开篇。

首先去Protobuf-net的Google下载点下载protobuf-net类库:https://code.google.com/p/protobuf-net/downloads/list
这里用的是目前最新的protobuf-net r668
下载完毕后打开压缩包,在Full\unity中找到protobuf-net.dll将其添加到项目中。
接下来过程其实类似于我之前的一文章《Protobuf在Java中的简单实例》

①创建proto文件,定义协议格式
首先我们需要创建一个.proto文件来进行测试:

1
2
3
4
5
package com.beitown.net.msg;//包名
message TestMsg {
    required int64 Id=1;
    required string Name=2;
}

每个字段后标记的“=1”、“=2”这里就不解释了,之前的一篇Protobuf文章中已经做过概述。

②编译Proto文件生成.cs文件
这里我们需要用到一个编译工具ProtoGen,在之前下载的protobuf-net r668.zip中就有。
为了方便管理.proto和.cs文件以及编译快捷,我们可以写一个bat脚本来实现自动编译.proto文件,脚本如下:

1
2
3
@echo off
for /f "delims=" %%i in ('dir /b proto "proto/*.proto"') do protogen -i:proto/%%i -o:cs/%%~ni.cs
pause

(更多…)

Protobuf-net在Unity WebPlayer中的兼容解决方案

星期四, 五月 15th, 2014 11 views

由于项目需要所以使用了Unity + Protobuf。
但是问题随之而来,因为Protobuf是JIT运行时动态编译的,而Unity不支持这种运行时动态编译,同时Protobuf是基于.net2.0框架的,因此当项目发布在PC时,出现了异常:

1
2
3
4
5
6
7
8
9
10
ArgumentOutOfRangeException: Argument is out of range.

Parameter name: options
at System.Text.RegularExpressions.Regex.validate_options (RegexOptions options) [0x0003a] in /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/System/System.Text.RegularExpressions/Regex.cs:248

at System.Text.RegularExpressions.Regex..ctor (System.String pattern, RegexOptions options) [0x00017] in /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/System/System.Text.RegularExpressions/Regex.cs:214

at Google.ProtocolBuffers.Descriptors.DescriptorPool..cctor () [0x00000] in :0
Rethrow as TypeInitializationException: An exception was thrown by the type initializer for Google.ProtocolBuffers.Descriptors.DescriptorPool
......

这里使用的是Protobuf-Csharp包,通过排查,在发布时将PlayerSetting中Api Compatibility Level 设置成.Net 2.0即可解决。

如图

但当需要发布到WebPlayer的时候,发现一个基本无解的问题——WebPlayer PlayerSetting中的Api Compatibility Level按钮是灰色的!只支持.Net 2.0 subset模式,因此发布后依然无法解决protobuf异常问题。
(更多…)

Unity3D_TransForm相对世界坐标位移

星期四, 三月 14th, 2013 48 views

在Unity3D的简单位移教程里我们经常看到如下代码

1
2
3
4
function Update ()
{
        transform.Translate(new Vector3(1,0,0)*Time.deltaTime);
}

这里的Vector3 即创建一个方向向量,此时运行,物体会沿着其X轴方向位移,如图,即红色箭头方向

同理 修改Vector3的参数,即可使物体向任意一个方向进行位移,这里的Time.deltaTime在文档里的解释是:

“放在Update()函数中的代码是以帧来执行的.如果我们需要物体的移动以秒来执行.我们需要将物体移动的值乘以Time.deltaTime”

这样就确保了移动速度不至于过快

问题来了,这个物体的旋转方向已经改变,使用上文的方法,物体只会继续向着自身的x轴方向移动,如图,我们旋转角度已偏移,自身坐标角度与世界坐标角度已不重和

如果需要仍旧按照世界坐标的X轴方向运动
这里有两种方法,方法一,继续使用传统方法,但要进行一个向量的换算

方法二,查看API可以知道,translate这个方法其实还有第二个参数relativeTo(相对于)

function Translate (x : float, y : float, z : float, relativeTo : Space = Space.Self) : void

默认不写的话即为Space = Self,如果要相对于世界坐标的话,代码如下

1
2
3
4
function Update ()
{
        transform.Translate(new Vector3(1,0,0)*Time.deltaTime,Space.World);
}

此时即可相对于世界坐标的x轴方向运动了

同理如果希望相对于任意Gameobject的坐标进行运动,这里将Space.World 改成 GameObject.Transform 即可

虽然只是一个U3D函数拓展的使用方法,但常常容易被人们忽略,继而去自己编写向量转换或其他的方法。其实有时候多查一下API,看看是否已有可实现的方法,不失为一个好的习惯。

谢谢关注。共勉。

BeiTown
2013.03.14

Unity3D-FSM有限状态机的简单设计

星期三, 三月 13th, 2013 600 views

在之前的文章里介绍了一个基础U3D状态机框架(Unity3D游戏开发之状态流框架)即大Switch的枚举状态控制。这种方法虽然容易理解,编程方法也相对简单,但是弊端是当状态变得复杂之后,或需要添加一种新的状态时,会显得非常混乱并且难以下手。故我们需要引进一种更高级的状态机技术来避免这些问题。网上有一些讲述U3D-FSM状态机的文章,但都不针对基础讲解,而且大多带有冗余的与状态机不相关的代码,基础不好的读者容易看不清FSM状态机的核心所在。这里针对网上的一些文章和代码做了一个整理,意图使之简单易懂。

这里关于FSM有限状态机这类名词的解释这里就不再说明了,感兴趣的朋友可以自己去百度下(度娘链接),本文只说重点。

首先是状态机基类State.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * 状态基类
 */

public class State[entity_type>
{
    public entity_type Target;
    //Enter state  
    public virtual void Enter (entity_type entityType)
    {
       
    }
    //Execute state
    public virtual void Execute (entity_type entityType)
    {
       
    }
    //Exit state
    public virtual void Exit (entity_type entityType)
    {
       
    }

}

基类之所以设计成含有3个小的状态方法是因为,通常在游戏中有些行为都只是在进入或退出某个状态时出现的,并不会发生在通常的更新步骤中。这样设计就可以有效的将持续性调用语句和一次性调用语句有效的区分开来。(举例:发送技能时的特效,有些是持续性而有些又是一次性的)

接下来我们编写状态机代码,来使直接的这个基类的各个方法运作起来:
(更多…)

Unity3D协程闭包事件执行定时器

星期一, 三月 11th, 2013 124 views

介于U3D没有一个自带的事件执行定时器,所以打算自己动手做一个,基本思路如下,先用伪代码来写了

1
2
3
4
5
6
void timer(int time,Func func){

wait(time);//等待N秒
func();//执行传入的函数

}

最开始的思路是用闭包加线程来实现,之后和群里的朋友讨论了下,经过提示其实可以避免去碰线程这种bug多发产物,取而代之的是U3D包里自带的一个协程MonoBehaviour.StartCoroutine

先来完善下我们的事件定时器,惯例直接上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using UnityEngine;
using System.Collections;
using System;

public class EventTimer : MonoBehaviour {


    public IEnumerator Timer(float waitTime , Func[bool> func)
    {
        yield return new WaitForSeconds(waitTime);
        func();
   
    }

}

(更多…)

Unity3D摄像机高级控制

星期一, 三月 11th, 2013 619 views

在游戏场景中,通常摄像机如果需要进行一些不规则的固定运动,比如片头的场景摄像机的移动,此时如果通过代码来控制,虽然可以实现但调试过程并不直观,所以我们可以通过绑定摄像机动作来达到这一效果。
创建动作的过程这里不再赘述,前面的文章中有详细的讲解。

首先将创建好的动作绑定至摄像机,利用关键帧补间动画进行摄像机运动控制,如图

点击播放即可查看摄像机的实时运动效果,这里主要是针对xyz的位置及角度6个参赛进行调整,从而实现电影版的摄像机运动效果,这里我们且将动作命名为Move,并绑定至1号摄像机上

接下来我们创建一个摄像机管理脚本 CameraManger.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
using UnityEngine;
using System.Collections;

public class CameraManger : MonoBehaviour {

    public GameObject Camera_1;
    public GameObject Camera_2;
    public GameObject Camera_3;
   

    // Use this for initialization
    void Start () {
   
    }
   
    // Update is called once per frame
    void Update () {


        switch (Main.state)
        {
            case Main.STATE.READY:
                onActiveFalse();
                Camera_1.SetActive(true);
                Camera_1.animation.Play("move");

                break;

            case Main.STATE.START:
                onActiveFalse();
                Camera_2.SetActive(true);                
                break;

            default:
                break;

        }
   
    }

    void onActiveFalse()
    {
        Camera_1.SetActive(false);
        Camera_2.SetActive(false);
        Camera_3.SetActive(false);
    }
}

(更多…)

Unity3D碰撞检测及Trigger触发器的使用及注意事项

星期六, 三月 9th, 2013 2,107 views

首先新建一个Cube,其本身就已自带了碰撞器Collider,如图

要使用Trigger检测物体进入,则需要勾选Is Trigger选项
碰撞检测触发器Trigger 有别于碰撞检测器 Collision,其可以不受物理效果影响,一些可穿透区域的碰撞检测,可以使用Trigger来进行碰撞检测
常用方法如下:
OnTriggerEnter 进入时
OnTriggerExit 离开时
OnTriggerStay 处于时

同上碰撞检测器 Collision 也有3个方法:
OnCollisionEnter
OnCollisionExit
OnCollisionStay

这里我们需要为跑道添加一个终点撞线的机制,所以使用可穿透的碰撞检测触发器Trigger

代码如下:

1
2
3
4
5
    void OnTriggerEnter(Collider collider)
    {
        print(collider.gameObject.name + ":" + Time.time);
     
    }

OnTriggerEnter传入的参数必须为Collider,故能触发该函数的对象必须具有Collider组建。这里我们用的是角色控制器Character Controller 自带了Collider组建
此时每当有角色撞线时即会打印角色名及系统时间
(更多…)

Unity3D角色控制器的使用及游戏对象移动速度控制

星期四, 三月 7th, 2013 295 views

首先是角色控制器的添加 选定模型对象 在其Inspector视图中选择Add Component -> Physics -> Character Controller 出现组建如下图

此时模型对象上会出现一个胶囊体,通过改变Center、Radius以及Hight的值来调整胶囊体的位置,使之恰好包裹住模型对象,如下图


(更多…)

Unity3D模型导入与动画播放

星期二, 三月 5th, 2013 102 views

首先是模型的导入,方法比较多,但常规的是将FBX模型文件拖放至Project视图中即可自动载入,这里以某狼人模型为例,导入后效果如图,材质及动画都已绑定好,详细操作方式和注意事项后面文章会叙述。

下面叙述下如何用代码来对模型的动画播放进行控制

动画都是预先由美术设计好的,并且已经到处为资源文件,通过载入Unity中并与模型绑定即可,如图

animation中列出的即是此模型所绑定的动作动画,最上方的为默认动画设置,勾选下方play automatically 选项后即可自动播放默认动画。

现在我们通过脚本来控制动画播放。以最简单的为例,大家自己举一反三:

1
2
3
4
5
6
7
8
9
10
11
12
using UnityEngine;
using System.Collections;

public class AnimationManger : MonoBehaviour {
   
    // Update is called once per frame
    void Update () {

              gameObject.animation.Play("这里输入动作名 如 run");

    }
}

注意动作名必须和Animation表单中的一致,将脚本绑定到该Gameobject上,运行,效果如同

可以看到狼人开始奔跑起来了。

通过代码量的扩充我们即可达到自由超控动作动画的播放。
本章节仅为动画播放最基础教程,更多高级教程欢迎继续关注。

BeiTown
2013.03.05