您好,欢迎来到爱问旅游网。
搜索
您的当前位置:首页u3d开发第三人称摄像机

u3d开发第三人称摄像机

来源:爱问旅游网


创建第三人称角色控制器

本教程的宗旨不是指导读者如何使用Unity中的第三人称摄像机,而是教读者如何自己开发一个简单的第三人称角色控制器。

准备角色

首先,需要一个包含3个动画循环的角色,即:空闲循环、行走循环、跑动循环。

创建工程和场景

创建一个虚拟的游戏场景,以便角色在其中走动。

1.创建一个工程

\"File -> New Project\"

导入标准资源包(standard asset package),以便能够获得需要的天空盒(sky box)和地形纹理。

2. 创建一个场景,其中包含纹理地形,天空盒和平行光:

- 第一,创建一个地形:

\"Terrain -> Create Terrain\"。

- 第二,创建一个平行光,并对它进行旋转,从而使之照亮地形:

\"GameObject -> Create Other -> Directional Light\"

- 第三,在Hierarchy中选中地形(Terrain),在Inspector中选中“Paint Terrain Texture”按钮,并添加一个默认的纹理。

- 第四,\"Edit -> Render Settings\",然后在Inspector中设置Skybox的材质。

最终的效果,如下图:

导入角色

在Project Panel中右键单击,选择“Import New Asset”,从弹出的对话框中选择需要导入的角色。当角色导入后,你会在Project panel中看到角色prefab。

输入设置

需要创建的角色控制器很简单,它有一个行走和跑动选项,因此我们需要设置输入选项,以便控制向前,后退,向左,向右,以及在走动和跑动之间切换等。当然,如果你添加了其他的动画,如跳动,攻击等,你还需要更多输入选项。

执行:

\"Edit -> Project Settings -> Input\".

在Inspector上会变成如下形式:

展开Axis部分,其中有17个不同类型的输入形式。在顶部,有“Horizontal”和“Vertical” ,它包含了left, right, forward和backwards输入选项。他们有positive和negative两个值,分别控制不同的方向,支持键盘以及其他类似输入设备,如游戏手柄等。

不需要17个输入选项,因此进行如下改变:

1.将17设置成3。

2.保留“Horizontal”和“Vertical”选项,可以改变其中的关于按键的设置,默认情况下,up, down, left, right对应着键W, A, S and D。

3.选择第三个选项(默认为Fire1),展开它的设置:

- 重新命名 \"Run\"。

- 将Positive 设置为\"left ctrl\"。

- 将Negative设置为空。

- 将alternative Positive和Negative options 设置为空。

下面让我们来看一下Horizontal和Vertical轴,Horizontal指的是你的左右控制,Vertical指的是前后控制。

需要设置一个正值和一个负值,另外还可以提供另外一套按键,设置的时候一定注意

不用发生冲突。

动画周期

在执行角色控制之前,需要对动画进行配置。导入的角色中包含了3个动画循环,如果你打开3ds Max,你会在时间线上发现这些动画,首先是静止动画,然后是走动,接着是跑,当我们导入此角色的时候,这些动画同样会一起导入,但我们需要告诉Unity,这里有3个动画,分别指明每一个动画循环的起始帧和终止帧,并给每一个动画循环进行命名,以便于我们在控制脚本中进行调用。

动画的时间线按照下面的形式进行设计:

Idle循环:0-180帧

Walk循环:200-230帧

Run循环:250-274帧

在Project面板上选择此角色,在Inspector中查看它的设置。从中找到FBX Importer部分,如果你展开了这些设置,你将在下面看到动画序列选项。

我们需要创建3个动画序列,点击右侧的+号,创建3个不同的内容,对他们进行命名,然后设置起始和终止帧,如下:

1. idle (0-180)

2. walk (200-230)

3. run (250-274)

完成上述设置后,点击Apply,Unity会自动打断此动画循环,形成3个不同的序列,我们可以在脚本中使用动画序列的名称。

最终的动画序列如下图:

你或许已经注意到了一个blend模式和一个loop选项,你可以设置动画混合模式和序列循环模式,但我们后面将使用脚本进行控制,所以这里使用默认设置。

当这些设置完成后,我们开始执行动画控制器了(character controller)。

放置角色

将角色从project中拖放到scene视图中,此时角色显示在scene中,同时在hierarchy中也会显示出来。

你或许需要在场景中对角色进行定位,一定要保证它的脚接触到地面(但要保证不要穿过地面,否则对象会掉下去)。

你可以使用窗口右上角的视角控制手柄来切换top,down,side, front和 perspective模式,最终角色的放置方式如下:

添加角色控制器组件(Character Controller)

现在我们需要在角色上添加一个\"Character Controller\" 以便Unity知道此对象为一个可运行的角色,在Hierarchy中选择角色:

Component -> Physics -> Character Controller

当Prefab警告窗口出现后,点击Add,接收这种改变,当添加角色控制组件后,我们需要缩放它的胶囊型碰撞器,以便它的尺寸和角色的尺寸相当,并将它放置在角色的周围(包裹在角色上)。

在Inspector中你可以看到角色控制的设置,调节到front和side视图,然后调整高度和半径,以便与它和角色相匹配,调整胶囊的中心值在正确位置。

对于我们的角色,设置高度为1.85,半径为0.4,Y中心值为0.93;如果你使用自己的角色,设置会有所不同。

调整胶囊的大小使之匹配角色的尺寸,调整它的位置,以便不穿越地形,如下图:

放置摄像机

接下来我们来设置这个摄像机,选择Main Camera,调整它的位置,以便于摄像机在角色的后面调整摄像机的角度,以便于稍微偏转一点,从另外一个角度上观察角色。

如果你此时运行游戏,你可以看到角色,处于闲置状态。你不能移动角色,我们需要写一个脚本来接收用户的输入,然后来掌握控制器,然后告诉角色模型来改变不同的动画循环。

创建并应用脚本(Script)

(1)首要的是创建一个脚本script,

在Project Panel上单击Create按钮,然后选择\"JavaScript\",这将在Project Panel中创建一个新的JavaScript。

(2)对脚本进行重命名\"PlayerCharacter\" 然后将其从Project Panel中拖放到角色上,以便使它们之间建立联系,现在脚本中的内容就应用在了角色上。

(3)打开脚本编辑器,修改其中的代码。

编写脚本

如果你曾经看过其他的3rd person控制器脚本,会发现它们很长,如果你是unity的初学者则会发现这些代码是很复杂的,下面的介绍会尽量的突出重点,从而使之更加容易理解。

(1)首先定义一些控制器要用到的非常重要的变量,

private var walkSpeed : float = 1.0;

private var gravity = 100.0;

private var moveDirection : Vector3 = Vector3.zero;

private var charController : CharacterController;

下面我们对上面的4条代码进行一下解释:

 walkSpeed是一个浮点型,存储了移动的速度

 gravity是另外一个浮点型,其中包含了重力加速度,用于保持角色位于地面上。

 moveDirection是一个Vector3(包含xyz坐标的变量)类型,存储了角色运动的方向。

 charController是一个角色控制器变量(character controller variable),我们将在此变量中设置前面添加的控制器,以便于我们能够在脚本中直接引用它。

(2)创建一个Start()函数,他将在游戏运行的时候,自动被调用,此函数会被用于初始化运行时。

function Start()

{

charController = GetComponent(CharacterController);

animation.wrapMode = WrapMode.Loop;

}

Start()函数类似于main() / winmain() 函数,它在脚本加载时自动被调用, Start() 只能被调用一次,不能多次执行。

上面脚本中的第一行,将前面创建的character controller赋给controller变量,第二行设置动画wrapMode 模式为\"loop\"。此语句和前面设置动画的loop选项框有相同的作用. ,但通过此语句,可以得到所有的动画的loop属性。

(3)接下来创建一个Update()函数,它时另一个重要的函数, start()和update() 的区别是,update()函数在每一帧都会自动调用。因此,所以应用在事件列表和实时行为脚本是很有用的。

function Update ()

{

}

我们的行为代码都添加在此函数中。

创建基本行为代码

首先,我们不需要角色能够在空中移动或转身。因此我们必须检测角色是否在地面上,如果角色在地面上,我们运行玩家移动角色,否则,角色将下落,直到接触地面为止。

因此在Update()函数的顶部添加一个if语句:

if(charController.isGrounded == true)

{

}

上面的代码的含义是,当角色控制器接触到地面后,我们可以执行if中的功能\"isGrounded\" 是一个条件,Unity可以自动的理解,当控制器角色接触到地面后,它的值变为true,如果没有接触到地面,则它的值为false。

如果角色没有在地面上,我们需要告诉Unity将角色降落到地面上,因此需要在if后面添加一些代码,提供一些重力的影响效果。

moveDirection.y -= gravity * Time.deltaTime;

上面这行代码将起到重力的作用效果,它将使角色下降,

将下面的代码放置在重力代码的后面:

charController.Move(moveDirection * (Time.deltaTime * walkSpeed));

上面的这一行新代码使用Move函数来移动角色,他是Unity中的函数,用于移动对象,我们将移动方向movedirection这个vector3赋给此函数,此函数中包含了xyz位置,并根据时间值来调整下降的速度。

换句话说,我们在movedirection的方向上以每秒walkspeed的速度移动对象。

如果你保存了脚本,并通过平移工具将角色拉高一定距离,那么当你松开鼠标的时候,你会发现,你的角色会自动向下降落,指导它触碰到地面。如果你的角色穿过地形,可以将角色拉高一些,从而保证角色的脚在地面上或高于地面。如果角色仍旧会穿过地面,则需要检查你事先设置好的碰撞体(胶囊),查看它的底部是不是和角色的脚相匹配,如果它们不匹配则,此碰撞体有可能已经穿过了地面。

因为我们已经施加了重力,下面让我们添加一些代码,以便于角色能够向前行走。在此之前,我们需要检查输入的Vertical axis,然后使之控制角色向前移动。

将下面的代码添加到isGrounded的IF中。

if(Input.GetAxis(\"Vertical\") > .1)

{

}

我们使用Input。GetAxis(“name”)来读取任何vertical axis轴的输入。如果输入值大于0.1,那么就会有一个向前的输入需求。Axes具有*。*值的原因是,模拟控制器有可能有一个读取的范围(控制速度会根据操作杆按下的距离而定)。我们也可以通过它的负值来控制相反的运动。

当按下向前的按钮后,if中的语句就会执行。

接下来,在我们告诉角色向前移动之前,我们需要有一个行走/跑动的切换选项,通常,当Ctrl被按下后,角色开始跑动,否则角色会行走。如果你只有一个行走速度,你可以跳

过此设置,只添加向前行走的代码。但很多游戏都至少具有2个不同的移动速度。因此,让我们创建另外一个if语句,它可以检测是否我们需要行走和跑动了。

将下面的代码放置在GetAxis(\"Vertical\")的if 语句

if(Input.GetButton(\"Run\"))

{

}

else

{

}

这个新的if语句使用GetButton监听Run按钮,如果run按钮按下的时候,我们可以执行角色的跑动,否则我们的角色只会行走。

因此,让我们在if中添加行走和跑动的代码。

animation.CrossFade(\"run\");

walkSpeed = 4;

上面的代码中放入到第一个if中(跑动)。第一行使用

animation.CrossFade(\"animation_name\") 来混合需要的动画,第二行设置行走速度(4是跑动的速度)。我们将下面的代码放置在else中:animation.CrossFade(\"walk\");

walkSpeed = 1;

上面的代码执行相同的功能,但混合仅行走动画,并且设置速度为1.

接下来我们向添加一些代码,使之能够在前进键释放后时角色返回空闲动画。

else

{

animation.CrossFade(\"idle\");

}

上面的代码中我们检测了向前、跑动,行走速度和空闲状态,我们现在想检测后退的运动,在if中添加下面的代码:

else if(Input.GetAxis(\"Vertical\") < -.1)

{

animation[\"walk\"].speed = -1;

animation.CrossFade(\"walk\");

walkSpeed = 1;

}

上面的代码检测负值(控制后退),然后将动画速度设置为-1,向后移动角色,混和动画为行走,速度为1.

此时如果按下play,你能够控制角色向前、向后行走,切换行走和跑动,然而在角色真的在执行动画时,它不能真的向前和向后运动。

将下面的代码放在IsGrounded的if中,放置在最后。

moveDirection = Vector3(0,0, Input.GetAxis(\"Vertical\"));

moveDirection = transform.TransformDirection(moveDirection);

上面的两行代码将设置垂直运动和运动方向,以便于角色真的向前移动。

我们现在还不能进行旋转,因此需要检测水平控制,来进行旋转操作,添加下面的代码,到上面代码的前面。

transform.eulerAngles.y += Input.GetAxis(\"Horizontal\");

上面的代码设置旋转方向,点击play,现在角色可以旋转了,但你可能会发现两个瑕

疵:

(1)如果你执行了后退操作后,当再次执行向前操作时,角色仍旧会执行向后的动画。

(2)If you turn on the spot without moving the character doesnt step.

(3)接下来让我们来修改这两个小bug。

(4)将下面的代码添加到行走的if中的最顶部。

(5)animation[\"walk\"].speed = 1;

(6)这将保证行走动画在你向前走的时候执行向前的操作。

(7)下面在IsGrounded的if中的陈述放置在设置旋转的eulerAngles前面:

(8)// Create an animation cycle for when the character is turning on the spot

(9)if(Input.GetAxis(\"Horizontal\") && !Input.GetAxis(\"Vertical\"))

(10){

(11)animation.CrossFade(\"walk\");

(12)}

(13)if语句检测如果角色在没有向前行走时,进行旋转,在旋转的时候播放行走动画。

(14)现在可以比较完美的执行动画了。

下面需要让摄像机跟踪角色了。

粘贴代码

下面是完整的代码:

private var walkSpeed : float = 1.0;

private var gravity = 100.0;

private var moveDirection : Vector3 = Vector3.zero;

private var charController : CharacterController;

function Start()

{

charController = GetComponent(CharacterController);

animation.wrapMode = WrapMode.Loop;

}

function Update ()

{

if(charController.isGrounded == true)

{

if(Input.GetAxis(\"Vertical\") > .1)

{

if(Input.GetButton(\"Run\"))

{

animation.CrossFade(\"run\");

walkSpeed = 4;

}

else

{

animation[\"walk\"].speed = 1;

animation.CrossFade(\"walk\");

walkSpeed = 1;

}

}

else if(Input.GetAxis(\"Vertical\") < -.1)

{

animation[\"walk\"].speed = -1;

animation.CrossFade(\"walk\");

walkSpeed = 1;

}

else

{

animation.CrossFade(\"idle\");

}

// Create an animation cycle for when the character is turning on the spot

if(Input.GetAxis(\"Horizontal\") && !Input.GetAxis(\"Vertical\"))

{

animation.CrossFade(\"walk\");

}

transform.eulerAngles.y += Input.GetAxis(\"Horizontal\");

// Calculate the movement direction (forward motion)

moveDirection = Vector3(0,0, Input.GetAxis(\"Vertical\"));

moveDirection = transform.TransformDirection(moveDirection);

}

moveDirection.y -= gravity * Time.deltaTime;

charController.Move(moveDirection * (Time.deltaTime * walkSpeed));

按照上面的步骤可以创建一个可以在场景运行的角色,然而,在我们创建的系统中有两个瑕疵:

1.摄像机不能跟踪角色。

2.角色可以在十分陡峭的地形上可以行走。

摄像机跟踪

当角色在走动的时候,我们希望摄像机在后面跟随角色运动,有3种方法可以完成此功能:

(1)从Hierarchy中拖动Main Camer到character prefab上,这样将摄像机绑定到控制器上。

(2)创建一个光滑跟着摄像机(smooth follower camera),它将绑定在角色上。

(3)创建一个轨道摄像机(orbital camera)。

第一种方法是最简单的,它可以将摄像机作为角色的一个子集(child),如果想测试场景运行的时候,可以采用此方法,但这种方法设置的摄像机运动有一些粗糙,它并不是一个最好的跟踪器。

第二种方法,我们施加一个光滑跟踪组件(smooth follow component)到摄像机上,然后将其与角色相关联,从而获得一个更好的跟踪器。

第三种方法稍微有一些复杂,可以参看另外其他的一些指导文档。

在这里我们使用第二种方法,执行下面的基本步骤。

1.在hierarchy中选择摄像机。

2. 选择【Component 】/【Camera Control】/【Smooth Follow】。

这样可以将一个光滑跟踪组件(smooth follow component)添加到摄像机上,我们接下来需要将它和角色连接起来。

1. 在Hierarchy中选择Main Camera。

2. 在Inspector中查看Smooth Follow script部分,如下图。

3. 设置目标(target)为角色的transform。

如果你测试此游戏,摄像机将跟随角色,但将会脱离位置,因此我们需要设置摄像机的位置。

设置Height和Distance,以便于它在希望的位置。当你在恰当的位置上测试游戏,你会发现摄像机会跟随角色运动,并光滑的配合角色运动,没有粗糙的感觉。

坡度的限制

如果你曾经构造了一些地形,如山坡,悬崖等,那么你会发现,及时坡度很陡峭,角色仍旧可以走上去,这是不可能的,因此,我们需要采取技术防止这一情况,设置一个坡度限制可以很方便的防止角色走上一个斜面,因为我们连接在角色上的角色控制器组件(character controller component)中包含了一个坡度限制。

1. 在Hierarchy中选择角色。

2. 在Inspector的角色控制器部分处查看“Slope Limit”。

默认为90度,这是很陡峭了,将它们设置为40-50.

其他说明:

伴随摄像机

当伴随摄像机工作的时候,必须考虑到摄像机碰撞检测问题,但是要做到这些需要掌握其他一些机能,这已经超出了本文的范畴,很快我们要提供一个关于高级摄像机的应用文章。

读取动画时间

知道怎样读取动画的时间是非常有必要的,很简单,只需要下面的代码:

animationTime = animation[\"name_of_animation\"].clip.length;

在角色上添加纹理

我们没有考虑到怎样在角色上添加纹理,但这是很简单的,和很多模型导入方法一样,单独导入纹理,然后在Inspector 中打开材质,从中为每一个材质选择纹理。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- awee.cn 版权所有

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务