Unity3D游戏制作场景角色移动设备设置等.docx

上传人:b****3 文档编号:27509383 上传时间:2023-07-02 格式:DOCX 页数:48 大小:5.73MB
下载 相关 举报
Unity3D游戏制作场景角色移动设备设置等.docx_第1页
第1页 / 共48页
Unity3D游戏制作场景角色移动设备设置等.docx_第2页
第2页 / 共48页
Unity3D游戏制作场景角色移动设备设置等.docx_第3页
第3页 / 共48页
Unity3D游戏制作场景角色移动设备设置等.docx_第4页
第4页 / 共48页
Unity3D游戏制作场景角色移动设备设置等.docx_第5页
第5页 / 共48页
点击查看更多>>
下载资源
资源描述

Unity3D游戏制作场景角色移动设备设置等.docx

《Unity3D游戏制作场景角色移动设备设置等.docx》由会员分享,可在线阅读,更多相关《Unity3D游戏制作场景角色移动设备设置等.docx(48页珍藏版)》请在冰豆网上搜索。

Unity3D游戏制作场景角色移动设备设置等.docx

Unity3D游戏制作场景角色移动设备设置等

Unity3D游戏制作

开博写Unity的东西也写了好多,但大部分都是翻译,原创很少,接下来的一段日子,我会多写一些原创文章,介绍一些在项目中积累的简单实用的技术。

一:

 3D横版场景的角色移动控制

一、导入场景,并在场景中加入TouchPlane

TouchPlane为鼠标屏幕时的Raycast平面,如下图场景中的绿线部分。

由于是横版场景,地面一般是平坦的,所以可以选择进行一个平面来作为计算鼠标投射交点。

之所以是绿线,是因为我disable该平面的MeshRender,该平面的Inspector视图如下:

值得注意的是:

1、该平面使用BoxCollider,而不用MeshCollider,这样做的好处是可以减少碰撞的计算量;

2、Tag设定为“Plane”,这是为了鼠标点击时的Raycast选取;

3、Layer设定为“TouchPlane”,这样做也是为了以后进行Raycast鼠标选取操作。

二、设定角色Component

角色Inspector视图如下图所示:

一共四个Component:

Animation、Rigidbody、CapsuleCollider以及MoveController。

Animation组件主要是角色的动作动画;

Rigidbody组件是为了角色的移动,这个我在后面会解释,这里还有一点需要注意就是不使用“UseGravity”,这样做一是因为角色只在地面上跑(如果你的游戏需要角色有跳跃功能,那么应该使用“UseGravity”,二是可以在不影响效果的同时,减少模型的物理计算);

CapsuleCollider是碰撞器,与该文章所介绍移动内容没有关系;

MoveController是自定义的角色移动控制组件,其中MoveController.cs为其对应脚本。

三、如何移动角色

流程可设定如下:

1、鼠标点击地面,通过屏幕位置来计算出其所在三维空间中角色移动的目的位置。

2、将角色从当前位置移动到鼠标点击位置

这样,我们就根据上述两个步骤来完成人物的移动操作。

(1)鼠标拾取操作

[csharp]viewplaincopyprint?

1.void Move()  

2.{  

3.    if(Input.GetMouseButtonDown(0))  

4.    {  

5.        // m_layerMask是指TouchPlane的layer数,这也是为什么之前在设定//TouchPlane时要设定其layer的原因,这样做是为了方便鼠标拾取  

6.        m_layerMask = 1 << 8;  

7.        // 根据鼠标在屏幕空间的位置计算射线  

8.        m_ray = Camera.main.ScreenPointToRay(Input.mousePosition);  

9.        // 进行三维场景中的射线求交  

10.        if (Physics.Raycast(m_ ray, out m_ hitInfo, 100, m_layerMask))  

11.        {  

12.            // 如果拾取的tag为“Plane”的话  

13.            if (m_hitInfo.transform.tag == "Plane")  

14.            {  

15.                // 将角色朝向目标点  

16.                LookatTargetPos(m_ hitInfo.point);  

17.            }  

18.        }  

19.    }  

20.}  

voidMove()

{

if(Input.GetMouseButtonDown(0))

{

//m_layerMask是指TouchPlane的layer数,这也是为什么之前在设定//TouchPlane时要设定其layer的原因,这样做是为了方便鼠标拾取

m_layerMask=1<<8;

//根据鼠标在屏幕空间的位置计算射线

m_ray=Camera.main.ScreenPointToRay(Input.mousePosition);

//进行三维场景中的射线求交

if(Physics.Raycast(m_ray,outm_hitInfo,100,m_layerMask))

{

//如果拾取的tag为“Plane”的话

if(m_hitInfo.transform.tag=="Plane")

{

//将角色朝向目标点

LookatTargetPos(m_hitInfo.point);

}

}

}

}

 

(2)角色移动操作

[csharp]viewplaincopyprint?

1.void LookatTargetPos(Vector3 tarPos)  

2.{  

3.    // 判断当前角色是否可以移动  

4.    if (!

m_bWalk)  

5.        return;  

6.    // 记录下目标点  

7.    m_targetPos = new Vector3(tarPos.x, tarPos.y, tarPos.z);  

8.    // 将角色朝向目标点  

9.    transform.LookAt(m_targetPos);  

10.    // 改变移动State  

11.    m_bMoving = true;  

12.}  

voidLookatTargetPos(Vector3tarPos)

{

//判断当前角色是否可以移动

if(!

m_bWalk)

return;

//记录下目标点

m_targetPos=newVector3(tarPos.x,tarPos.y,tarPos.z);

//将角色朝向目标点

transform.LookAt(m_targetPos);

//改变移动State

m_bMoving=true;

}

 

MoveController.cs中的Update函数如下:

[csharp]viewplaincopyprint?

1.void Update ()   

2.{  

3.    Move();  

4.    // 如果可以移动的话  

5.    if (m_bMoving)  

6.    {  

7.        // 改变角色的Animation  

8.        animation.CrossFade("Run");  

9.        // 设定rigidbody的速度,由于之前已经将角色朝向目标点,所以现在的速度朝向即为transform.forward  

10.        rigidbody.velocity = transform.forward * 8.0f;  

11.      

12.        // 判断角色是否该停止移动  

13.        if (Vector3.Distance(transform.position, m_targetPos) < 0.1f)  

14.        {  

15.            rigidbody.velocity = Vector3.zero;  

16.            m_bMoving = false;  

17.            animation.CrossFade("Idle");  

18.        }  

19.    }  

20.}  

voidUpdate()

{

Move();

//如果可以移动的话

if(m_bMoving)

{

//改变角色的Animation

animation.CrossFade("Run");

//设定rigidbody的速度,由于之前已经将角色朝向目标点,所以现在的速度朝向即为transform.forward

rigidbody.velocity=transform.forward*8.0f;

//判断角色是否该停止移动

if(Vector3.Distance(transform.position,m_targetPos)<0.1f)

{

rigidbody.velocity=Vector3.zero;

m_bMoving=false;

animation.CrossFade("Idle");

}

}

}

 

四、实现效果

通过以上设置即可控制角色在横版场景中的移动,效果图如下:

 

五、小结

1、该做法只适合平面的地表,如果是有起伏的,则需要使用Navmesh或其他trick来解决。

2、该做法并没有让角色与地面去做碰撞,因为本身是平面的,所以直接限定其y值,不让其使用重力作用,这样的好处可以避免不必要的物理计算。

3、角色的移动可以不用rigidbody来搞定,一般的做法还是通过Time.deltatime来一帧一帧来计算步长、移动物体,这里只是给出另外一种方法,原来其实是一样的。

二:

如何渲染3D角色

本文主要介绍一下如何利用Shader来渲染游戏中的3D角色,以及如何利用Unity提供的SurfaceShader来书写自定义Shader。

一、       从Shader开始

1、通过Assets->Create->Shader来创建一个默认的Shader,并取名“MyShader”。

2、将MyShader打开即可看见Unity默认的Shader代码

[csharp]viewplaincopyprint?

1.Shader "Custom/MyShader" {  

2.    Properties {  

3.        _MainTex ("Base (RGB)", 2D) = "white" {}  

4.    }  

5.    SubShader {  

6.        Tags { "RenderType"="Opaque" }  

7.        LOD 200  

8.          

9.        CGPROGRAM 

10.        #pragma surface surf Lambert  

11.  

12.        sampler2D _MainTex;  

13.  

14.        struct Input {  

15.            float2 uv_MainTex;  

16.        };  

17.  

18.        void surf (Input IN, inout SurfaceOutput o) {  

19.            half4 c = tex2D (_MainTex, IN.uv_MainTex);  

20.            o.Albedo = c.rgb;  

21.            o.Alpha = c.a;  

22.        }  

23.        ENDCG  

24.    }   

25.    FallBack "Diffuse"  

26.}  

Shader"Custom/MyShader"{

Properties{

_MainTex("Base(RGB)",2D)="white"{}

}

SubShader{

Tags{"RenderType"="Opaque"}

LOD200

CGPROGRAM

#pragmasurfacesurfLambert

sampler2D_MainTex;

structInput{

float2uv_MainTex;

};

voidsurf(InputIN,inoutSurfaceOutputo){

half4c=tex2D(_MainTex,IN.uv_MainTex);

o.Albedo=c.rgb;

o.Alpha=c.a;

}

ENDCG

}

FallBack"Diffuse"

}

3、将该Shader赋给一个角色,就可以看到该Shader所能表达出的Diffuse渲染效果。

4、接下来我们将以此默认Shader作为蓝本,编写出自定义的Shader。

另外,该Shader所用到的参数,我们将在下一章节进行说明。

二、       实现多种自定义渲染效果

1、 BumpMap效果

如果想实现BumpMap效果,可对上述的Shader做如下修改:

1.1 在属性Properties中加入:

[csharp]viewplaincopyprint?

1.Properties {  

2.    _MainTex ("Base (RGB)", 2D) = "white" {}  

3.    _BumpMap("Bumpmap", 2D) = "bump" {}  

4.}  

Properties{

_MainTex("Base(RGB)",2D)="white"{}

_BumpMap("Bumpmap",2D)="bump"{}

}

1.2  在SubShader的变量中也进行相应修改:

[csharp]viewplaincopyprint?

1.sampler2D _MainTex;  

2.sampler2D _BumpMap;  

3.  

4.struct Input {  

5.    float2 uv_MainTex;  

6.    float2 uv_BumpMap;    

7.};  

sampler2D_MainTex;

sampler2D_BumpMap;

structInput{

float2uv_MainTex;

float2uv_BumpMap;

};

1.3  最后修改surf函数,加入对Normal分量的计算:

[csharp]viewplaincopyprint?

1.void surf (Input IN, inout SurfaceOutput o) {  

2.

 pre"> half4 c = tex2D (_MainTex, IN.uv_MainTex);  

3.    o.Albedo = c.rgb;  

4.    o.Alpha = c.a;  

5.    o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));  

6.}  

voidsurf(InputIN,inoutSurfaceOutputo){

half4c=tex2D(_MainTex,IN.uv_MainTex);

o.Albedo=c.rgb;

o.Alpha=c.a;

o.Normal=UnpackNormal(tex2D(_BumpMap,IN.uv_BumpMap));

}

这样,角色的材质部分即可变为如下形式(暂定BumpMap的Shader名为“MyShader1”):

然后,根据Base图来创建其NormalMap图,并拖入到BumpMap中即可。

BumpMap的效果显示如下:

说明:

(1)首先是title的解释

[csharp]viewplaincopyprint?

1.Shader "Custom/MyShader1"   

Shader"Custom/MyShader1"

这种表示表明了该Shader在编辑器中的显示位置,例如我们可在如下地方找到该Shader。

(2)其次是Properties

[csharp]viewplaincopyprint?

1.Properties {  

2.    _MainTex ("Base (RGB)", 2D) = "white" {}  

3.    _BumpMap("Bumpmap", 2D) = "bump" {}  

4.}  

Properties{

_MainTex("Base(RGB)",2D)="white"{}

_BumpMap("Bumpmap",2D)="bump"{}

}

Properties可通过如下语义进行声明:

name("displayname",propertytype)=defaultvalue

l “name”是与Shader脚本中对应的名字

l “displayname”是在材质视图中所显示的名字

l “propertytype”是指该property的类型,一般可有如下几种类型:

Range,Color,2D,Rect,Cube,Float和Vector

l “defaultvalue”是指该property的默认值

这里需要注意的是,如果你在Properties中加入了新的属性,那么你需要在CGPROGRAM中的SubShader中加入同样名字的参数。

(3)接下来是“LOD”语义词的解释。

这里的“LOD”主要是指Shader的LOD程度,即对于超出该范围的物体将不再通过该Shader进行渲染,具体的ShaderLOD说明可以参见:

(4)我们在SubShader中还加入了

[csharp]viewplaincopyprint?

1.sampler2D _BumpMap;  

2.float2 uv_BumpMap;  

3.              

sampler2D_BumpMap;

float2uv_BumpMap;

其中,_BumpMap是为了关联Properties中的_BumpMap属性。

而uv_BumpMap,是为了获取BumpMap图中的uv坐标。

(5)最后,我们在surf函数中获取每个顶点的纹理信息以及法线信息,这些信息将被应用于接下来的VertexFragment和PixelFragment。

[csharp]viewplaincopyprint?

1.void surf (Input IN, inout SurfaceOutput o) {  

2.    half4 c = tex2D (_MainTex, IN.uv_MainTex);  

3.    o.Albedo = c.rgb;  

4.    o.Alpha = c.a;  

5.    o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));  

6.}  

voidsurf(InputIN,inoutSurfaceOutputo){

half4c=tex2D(_MainTex,IN.uv_MainTex);

o.Albedo=c.rgb;

o.Alpha=c.a;

o.Normal=UnpackNormal(tex2D(_BumpMap,IN.uv_BumpMap));

}

其中,tex2D函数可以读取纹理_MainTex中的IN.uv_MainTex坐标位置的像素颜色值。

Albedo和Alpha分别获取该像素的RGB值和Alpha值,其中“Albedo”是一个漫反射参数,它表示一个表面的漫反射能力,即一个表面上出射光强与入射光强的比值。

具体介绍可见:

http:

//en.wikipedia.org/wiki/Albedo。

2、 Blinn-Phong效果

如果想实现Blinn-Phong效果,可对上述的Shader做如下修改:

2.1  在属性Properties中加入:

[csharp]viewplaincopyprint?

1._AmbientColor ("Ambient Color", Color) = (0.1, 0.1, 0.1, 1.0)  

2._SpecularColor ("Specular Color", Color) = (0.12, 0.31, 0.47, 1.0)  

3._Glossiness ("Gloss", Range(1.0,512.0)) = 80.0  

_AmbientColor("AmbientColor",Color)=(0.1,0.1,0.1,1.0)

_SpecularColor("SpecularColor",Color)=(0.12,0.31,0.47,1.0)

_Glossiness("Gloss",Range(1.0,512.0))=80.0

2.2  在SubShader的变量中也加入相应修改:

[csharp]viewplaincopyprint?

1.fixed4 _AmbientColor;  

2.fixed4 _SpecularColor;  

3.half _Glossiness;  

fixed4_AmbientColor;

fixed4_SpecularColor;

half_Glossiness;

2.3  最后修改surf函数,进行如下修改:

[csharp]viewplaincopyprint?

1.fixed4 c = tex2D (_MainTex, IN.uv_MainTex);  

fixed4c=tex2D(_MainTex,IN.uv_MainTex);

这里将原有的half4替换为fixed4,这样做是为了提高渲染的性能,因为fixed的精度较之half要低,更高的精度意味着更大的计算量,而这里fixed的精度已经足够,所以使用fixed替代half4,从而来降低计算消耗,增加渲染性能。

2.4  将“#pragmasurfacesurfLamber”改成“#pragmasurfacesurfCustomBlinnPhong”,同时加入与其对应的LightingCustomBlinnPhong函数来计算顶点光照。

[csharp]vie

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 环境科学食品科学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1