-
原文见
/bbs/?tid=5
第一步:
首先,我们从
主页下载最新版(此文以
UDK-2010-01<
/p>
版为
例)
安装
完成后,
我们找到
UDK-2010-01
文件夹,
对其复制粘贴创建一个副本,
将目
录名改成你喜欢的名字,比如我创建为
KingdomWorld
,以后文章都以
KingdomWorld
为例。<
/p>
(
以下步骤将对其进行大量修改,创建
副本的目的是为了保留原版
)
第二步
2.1.
进入
KingdomWorldDevelopmentSrc
目录,找到
UTGameContent
文件夹将
其全部删除。
2.2.
进入
KingdomWorldDevelopmentSrcUTGame
目录,
删除
以及
Classes
文件夹下面的所有文件,但是保留
Classes
文件夹。
2.3
.
进入
KingdomWorldDevelopmentSr
cUTGameClasses
目录,创建一个
do_not_
,键入以下内容
1.
class
do_not_delete extends object;
2.
defaultproperties
3.
{
4.
}
复制代码
创建此文件的目的是因为让
UTGame
目录顺利编译成
UTGa
me.u
文件,因为
UDK
免费版的原
因,启动编辑器和游戏他会自动寻找
UTGame.u
文件,所
以此包无法
全部删除(除非你有源代码级授权,就可以修改
UT
Game
目录指向)
第三步
进入
KingdomWorldUTGameContent
目录,删除所有文件
文件和
Kingdo
mWorldUTGameContentUIUI_Fonts_
文件除外,
这两个是系
统需要的底层
pak
包,字体和空场景,最好别删。
第四步
由于我们已经删除了所有关于
原始的
UTGame
的资源和代码文件,现在的文件夹
已经相对于来说是非常干净的了,那么,我们需要重新制作一个类似于
c
++
里面
的
main
< br>函数,因为
UTGame
目录已经被我们咔嚓掉了。他的
引用不到。
4.1.
来到
KingdomWorldDevelopmentSrc
目录,创建文件
夹
KWGame,
在其创建
Class
es
文件夹
4.2.
进入
KingdomWorldDevelopmentSrcKWGameC
lasses
目录
4.3.
创建一个
,键入以下
内容
1.
class KWInfo extends GameInfo;
2.
DefaultProperties
3.
{
4.
//
设置角色控制类
5.
PlayerControllerClass=class'erController'
6.
}
复制代码
4.
创建一个
,键入以下内容
1.
class
KWPlayerController extends GamePlayerController;
2.
DefaultProperties
3.
{
4.
}
复制代码
第五步
我们已完成了创建了我们自己
的初始化函数
KWInfo
和控制类函数
KWPlayerController,
那么我们需要吧编辑器的引用指向他们。<
/p>
5.1.
进入
KingdomWorldUTGameConfig
目录。
5.2.
打开
文件。找到
[fo]
中的
tGame
并修改成
D
efaultGame=
tServerGame
并修改成<
/p>
DefaultServerGame=
Controller
ClassName
并修改成
PlayerControlle
rClassName=erController
第六步
在这里,我们基本完成了整个
目录的精简,只留下我们需要的部分了,最后,我
们需要对整个工程进行优化,
去掉不存在和不需要的包的引用。
加入我们的引用
目录。
6.1.
进入
KingdomWorldUTGameConfig
目录。
6.2.
打开
文件。找到
[Engine]
中的
tPackages
并修改
成
ModEditPackages=KWGame(
吧
ModEditPackages
最前面的
;
去掉
)
6.2.2.
删除
+EditPackages=UTGameContent
这句
6.2.3.
找到<
/p>
[rdUser]
中的
MyDocume
ntsSubDirName
并修改成
MyDocuments
SubDirName=KWGame
========2
010-01-29
修改新增
==============<
/p>
6.3.
打开
文件。找到
[raction]
中的<
/p>
Name
并修改为
UISkinName=tSkin
6.4.
打开
文件。找到
[]<
/p>
部分。
6.4.1.
< br>将
[]
部分改为如下
(
其实就是吧
UTGame
改成
< br>Engine,
并且
去掉前缀
U
T)
1.
[]
2.
ConsoleClassName=e
3.
EditorEngine=orEngine
4.
UnrealEdEngine=alEdEngine
5.
DefaultOnlineSubsystemName=SubsystemPC
6.
UseStreaming=True
7.
ScoutClassName=
8.
GameViewportCl
ientClassName=ewportClient
9.
;DefaultPostProcessName=FX_Process
eenKismetWarnings=true
tweenPurgingPendingKillObjects=30
ntName=nt
FontName=MultiFont'UI_Fonts__Medium'
ontName=MultiFont'UI_Fonts_..MF_Large'
leFontName=MultiFont'UI_Fonts__Medium'
hadowVolumes=False
layerClassName=layer
ticleResize=1024
ticleResizeWarn=10240
20.;DemoRecordingDevice=cDriver
eColorClear=TRUE
复制代码
(
例如
ConsoleClassName=ole
改为
ConsoleClassName=ole)
6.4.2.
找到
[oreClient]
部分删除节点所有文件,新增一行
+PlayerD
ataStoreClassNames=Store_OnlinePlayerData
如下:
1.
[oreClient]
2.
+PlayerDataSto
reClassNames=Store_OnlinePlayerData
复制代码
6.4.3.
找到
[Store_On
linePlayerData]
改为如下
(
< br>其实就是吧
UTGame
改成
E
ngine,
并且去掉前缀
UT)
1.
[Store_OnlinePlayerData]
2.
ProfileSetting
sClassName=ProfileSettings
3.
FriendMessages
ProviderClassName=Provider_OnlineFri
end
Messages
4.
Frie
ndsProviderClassName=Provider_OnlineFriends
复制代码
6.4.4.
找到
[pPackage
s]
改为如下
1.
[pPackages]
2.
bSerializeStar
tupPackagesFromMemory=TRUE
3.
bFullyCompressStartupPackages=FALSE
4.
Package=DefaultUISkin
5.
Package=EngineMaterials
6.
Package=EngineSounds
7.
Package=EngineFonts
8.
Package=EngineBuildings
9.
-Package=SoundClassesAndModes
复制代码
6.4.5.
找到
[esToForc
eCookPerMap]
去除所有节点。
6.5.
打开
文件。找到
[nfo]
部分。
6.5.1.
找
到
EmitterPoolClassPath
并
修
改
为
EmitterPoo
lClassPath=
6.5.2.
找
到
DecalManagerClassPath
并
修
改
为
DecalMa
nagerClassPath=
7.
删除
KingdomWorldUTGameConfig
下
所有
UT
开头的
ini
文件,并且重新进
入编辑器,就会自动生成
UT
开头的
ini
了
<
/p>
========2010-01-29
修改新增
==============
总结:
至
此,你已经完成
UDK
目录的精简,并且删除了
UTGame
的全部内容,在接下来
的章节,我会一步
步介绍如何在这个精简工程中,全部制作属于自己的东西
这时
候你打开
UDK
编辑器,
可能需要等待
一会的时间,
因为他在重新编译一些东
西,耐心等待一下就可以
了。
下一章节预告【跟着楼主做游
戏之】《建立一个空工程
-
下》建立一个空的
< br>VS
工程,并且调试
KWGame
项目。
(请大家提前安装
vs20
08
或者
vs2005
,最好使用
p>
vs2008
,
vs2003
是不可以的,
因为有个脚本调试插件,他只能在
vs
2008
或者
vs2005
中运行)<
/p>
另外本文的大部分内容,阅读者最好有一定的编程基础,多以代
码为例讲解。
如果你确定看完了
《建立一个空工程
-
上》
这
篇,并且没有问题,那么接着和我学习把。
第一步:
首先确保机器已经安装
p>
vs2008(
或者
vs2005
,以后文章都以
vs2008
为例
),
然后安装
nFringe
(nFringe
的
最
新
版
/?title=Tools:UnrealScript_Stud
io:Releases
可以在这里
找到
,
目前附件传的是
也是截止发帖时候
的最新版,此插件有
30
天使用限制,我先看大家的下载次数吧
,至少
30
天内我暂时不会公开破解补丁
)
第二步:
2.1.
< br>打开
VS2008
,选择左上角菜单中的【文件】
--
【新建】
--
【
项目】
2.2.
选择
UnrealEngine 3 Licensees Project
2.
3.
检查【创建解决方案的目录】的勾是否已被去掉。
2.4.
位置填写为
安装目录
:KingdomWorldDevelopmentSrcKWGa
me
2.5.
名称为
KWGame(
注意大小写
),
点击确定
.
2.6.
打
开
目
录
KingdomWorldDevelop
mentSrcKWGameKWGame
将
其
所
有
文
件
剪
切
至
KingdomWorld
DevelopmentSrcKWGame
2.7.
打开目
录
KingdomWorldDevelopmentSrcKWGame
删除
KWGame
文件夹
(
此时里面那个
文件夹应该没有文件,都被你剪切到上面了
)
2.8.
打开目录
KingdomWorldDevelopmentSrcKWGame
使用
vs2008
打开
工程
第三步:
3.1.
选择左上角菜单中的【项目】
--
【
KWGame
属性】
3.2.
设置如下参数。
General
中
Game
中的
Target
Game
为
UnrealEngine 3 Mod
UCC Path
为
安装目录
:
Reference
Source Path
为
安装目录
:KingdomWorldDevelopmentSrc
Build
中
Script
Outputs
中
p>
的
Manually
set
UCC
output
directory
为
安
装
目
录
< br>:KingdomWorldUTGameScript
Debug
中
Start
Action
中的
Start Game
Executable
为
安装目录
:
Load
map
at
startup
为你的地图文件名,如我们为默认上次没删的
则填写为
EnvyEntry
Start with
speacified game
为
勾上
Enable unpublished mods
勾上
Open log window at
postions
并且设置为
0 Left,0 Top
第四步:
4.1.
< br>进入目录
KingdomWorldDevelopmentSrcKWGame
,将
Classes
文件夹改名为
p>
Classes1
4.2.
在
vs2008
里选中
KWGame
工程点击右键,选择【添加】
--
【新建文件夹】
p>
4.3.
讲其文件夹名命名为
Classes
4.4.
关闭
vs2008
,进入目录
KingdomWorld
DevelopmentSrcKWGame
,删除
Class
es
文件夹,
将
Classes1
p>
改名回
Classes
(
因为在上篇文章里这个文件夹下有
2
个文件,
先改名是为了防止
vs2008
里创建同名文件
夹
失败
)
4.5.
< br>打开目录
KingdomWorldDevelopmentSrcKWGame
使用
vs2008
打开
工程
4.6.
在
vs2008
里选中
KW
Game
工程中,选中
Classes
目录,点击右键,选择【添加】
--
【添
加现有项】
选
择
< br>KingdomWorldDevelopmentSrcKWGameClasses
< br>目
录
下
的
和
(上篇教程中创建)
4.7.
在
vs2008
里选中
KWGame
工程
(
选择工程路径不是
Classes<
/p>
文件夹
)
点击右键,选择【添
加】
--
【添加现有项】
选择
KingdomWorldUTGameConfig
p>
目录下的
和
(特别注
意添加文件的时候,在窗体那里添加按钮旁边有个小三角,选
择添加为链接)
总结:
至此,你可以在
VS2008
中调试你
的
UDK
项目了,在下面章节中,我们将会对这个工程继
续讲解。来做一个类似大菠萝的视角的游戏。
在以上的章节中,我们已经创建了
一个可以调试的
UDK
空环境,并且保证除了底层
Engine
部分,其他的资源都已经剔除掉了,在这里,我们接着开发属于
自己的游戏。
第一步:
我们先吧制作好的场景
p>
(可以参考其他教程或者等待其他人更新场景制作教程,
在此系列就
不
涉
及
大
p>
部
分
UDK
编
p>
辑
器
部
分
的
操
作
,
本
系
列
留
< br>给
程
序
员
)
放
入
KingdomWorldU
TGameContentMaps
中。
附带一个我随便制作的场景:
第二步:
进入
KingdomWorldDevelopmentSrcKWGame
目录,打开<
/p>
工程。
修改工
程属性的
Debug
中
Start
Action
中的
Load map at startup<
/p>
为
1001(
地图名
)
保存
(ctrl+s)
好后,我们可以在工程里按下菜单里的
【调试】
--
【启动调试】
(F5)<
/p>
来看效果。
如果能正确显示如上画面后,代表
你的
vs
工程配置没有问题了。
p>
接下来我们需要按下键盘的
键,呼出控制台
,输入
exit
并按下回车退出游戏界面
要注意的是,这时候虽然游戏关闭了,但是你的
VS
工程并没有关闭,
我们需要点击菜单里的【调试
】
--
【停止调试】
(Shift+F
5)
来停止工程。
第三步:
现在我们在
vs
工程里双击打开
Classes
< br>里的
进行编辑。
p>
可以发现,我们编写的
KWPlayerController
p>
类实际上继承了
GamePlayerController
类。
而
GameP
layerController
类是做什么的呢?(具体我们可以参考
API
手册
,
文章末尾的附件
)
其实是一个角色控制类。这么说吧,比如像在控制台里面的
命令,鼠标,键盘的操作,全部
都在这个控制类。
你可以吧他看成一个
Input
控制类。
所以,当你的鼠标点击的时候,我们可以在这个类里编写代码来实现你
需要的功能。
在学习写第一个类的时候,
我们可以加一小段调试代码,
从而观察环境里的这个类是否被运
行。
3.1.
新增一个
PostBeginPlay
方法
1.
simulated
event PostBeginPlay()
2.
{
3.
ginPlay();
4.
`Log(
角色控制类运行
5.
}
复制代码
新增代码后的效果:
我
们
通
p>
过
手
册
可
以
看
到
ayerCon
troller
的
父
类
是
Controller
而
Controller
中,则有一个
simulated
event PostBeginPlay
,所以我们可以重写,
他也会被自动调用
(
这是
UDK
p>
的
uc
脚本机制
)
其实追溯源头应该是
,而在此类有一个
event
PostBeginPlay();
在他继承的类中
重写,则会被自动调用。
而大部分类的主父类都集成了它,基本上类在运行后,都会首次寻找是否有
PostBeginPlay
方法来执行。你可以吧他看做这个类的构造函数吧。
p>
因为重写了他,
因为我们并不知道继承的
这个类的上面那些乱七八糟类里同样方法里做了一
些什么事情,所以我们试用
super
来调用父类的这个函数。在后面再插入我们自己需要编写
的代码。
第四步:
由于我们之前已经在
里的
DefaultProperties
方法里,
对<
/p>
PlayerControllerClass
的指
针已经赋值到了我们新做的
erController
里。所以这里我们新做的控制类
则会被调用。
在这里说一下,由于我们在
里修改的
[fo]
中的
DefaultGame
指向到
类,那么
KWInfo
你可以看做整个游戏的
main
函数。
而
PlayerControlle
rClass
是默认的用户控制类的指针
(
其他指针可以参考
API
,后面也会对一
< br>个个指针进行讲解)
而我们需要做的就是新建一个类继
承他,然后在
main
里绑定他。
<
/p>
现在,我们可以按下
F5
,看一下左边日
志窗口的提示信息。
如果你的界面如上图所示,那么你
的游戏已经成功调用了
erController
类。
很激动吧。你已经完成了你的第一个类的编写,并且通过
VS
已经调试出结果了。
还记得我们之前的步骤吗?按下键盘上的
键呼出控制台,输入<
/p>
exit
,并且在
vs
< br>里点击停
止调试就可以回到我们的界面来继续编码。
总结:
现
在你已经基本搭建好一个良好的
UDK
编写代码环境了,在下一
章节,我们将会继承一个
新的
Camera
类,通过
KWInfo
来绑定,来实现我们自己的游戏界面
的视角。
本文附带源码:
第一步:
我们先把制作好的角色模型
(可以参考其他教程或者等待其他人更新模型制作教
程,在此系
列就不涉及大部分
UDK
编辑器部分
的操作,本系列留给程序员)放
入
Ki
ngdomWorldUTGameContentCharactersHeroesAchilles
p>
中。
(KingdomWorldUTGameContent
p>
后的路径随便你定义,你直接放在
Content
< br>里
也行,这样做的目的仅仅是便于管理而已)
附带一个我随便制作的模型:
第二步:
打开工程。在
Classes
文件夹里添加一个
KWCamera
类。并编写如下代码
1.
class KWCamera
extends Camera;
2.
simulated event PostBeginPlay()
3.
{
4.
ginPlay();
5.
`Log(
摄像机类运行
6.
}
复制代码
我们编写了一个继承了摄像机类的
的类,从而完成我们自己的摄像机视角。
第三步:
找到我们之前编写的
文件,
在
Defau
ltProperties
内添
加一行
1.
CameraClass=class'KWCamera'
复制代码
这里要
特别说一下,
DefaultProperties
可以当做是
每个类的函数初始化的地
方,这里是不需要分号来换行的
p>
通过
CameraClass=
来赋值指针
为我们编写的类从而重载。
这时候
可以通过
F5
来调试一下,
看看日志窗
口
`Log(
摄像机类运行
这句话是
否正确执行。
在控制台输入
exit
退出游戏界面,
记得在
v
s
里停止工程,
我们来做一个出生类。
第四步:
打开工程。在
Classes
文件夹里添加一个
KWPawn
类。并编写如下代码
1.
class KWPawn
extends GamePawn;
2.
simulated event PostBeginPlay()
3.
{
4.
ginPlay();
5.
`Log(
出生类运行
6.
}
7.
8.
simulated function name
GetDefaultCameraMode( PlayerController
RequestedBy )
9.
{
10. `Log(
开始获取默认摄像机模式
11. `Log(
设置为
Isometric
模式
12. return 'Isometric';
13.}
14.
tproperties
16.{
17. //
删除场景内原有的元素
18. (Sprite)
19. //
创建动态环境光照对象
--
用于
InitialSkeletalMesh
对象
(
使用
LightEnvironment
成员赋
值
)
20. Begin Object
Class=DynamicLightEnvironmentComponent
Name=InitLightEnvironment
21. ModShadowFadeoutTime=0.25
22. MinTimeBetweenFullUpdates=0.2
23.
AmbientGlow=(R=.01,G=.01,B=.01,A=1)
24.
AmbientShadowColor=(R=0.15,G=0.15,B=0.15)
25.
LightShadowMode=LightShadow_ModulateBetter
26. ShadowFilterQuality=SFQ_High
27. bSynthesizeSHLight=TRUE
28. End Object
29.
30. //
添加进组件库
31. (InitLightEnvironment)
32.
33.
//
创建骨骼模型
34.
Begin Object Class=SkeletalMeshComponent
Name=InitialSkeletalMesh
35. CastShadow=true
36.
bCastDynamicShadow=true
37.
bOwnerNoSee=false
38. //
使用组件库里动态创建的环境光照对象
InitLightEnvironment
39.
LightEnvironment=InitLightEnvironment;
40. BlockRigidBody=true;
41. CollideActors=true;
42. BlockZeroExtent=true;
43. //
物理引擎包
44. //PhysicsAsset=PhysicsAsset'Achi
lles_es_
Full_Apa'
45. //
动画包
--
序号
0
46. //AnimSets(0)=AnimSet'Achill
es_es_Full_A
as'
47.
//
动画模板
48. //
AnimTreeTemplate=AnimTree'Achilles_es_
F
ull_Aat'
49.
//
模型文件
50. Sk
eletalMesh=SkeletalMesh'Achilles_es_Fu
l
l_Amesh'
51. End Object
52.
53. //Mesh
来自
GamePawn
的基类成员
(
貌似是设置出生角色
)
54.
Mesh=InitialSkeletalMesh;
55.
//
添加进组件库
56.
(InitialSkeletalMesh);
57.}
复制代码
这段代码我说明两个地方。
一个是<
/p>
defaultproperties
里面的成员,这个我是参考
原本的
UDK-
文件复制过来。并且
我
对如上代码做了相应的注释。由
于
我提供的资源包里只有模型文件。所以其他
资源的属性我都注释掉了。
< br>
另外一个是
simulated function name
GetDefaultCameraMode( PlayerController
RequestedBy )
这个方法会在
Camera
p>
启动后调用得到。
之所以我传入
return
'Isometric';
是因为通过观察
< br>里面的
UpdateViewTarget
方法,并没有
这么一个字符串,所以我是随便写的,你也可
以随便写一个,在后面我们继承的
Camera
类中,重写
UpdateVie
wTarget
方法
取得值来进行处理。所以这里的
'Isometric'
你改成
'xx','yy
','bb'
都可以
第五步:
找到我们之前编写的
文件,在
DefaultPropertie
s
内添加两行
1.
bDelayedStart=false
2.
//
设置出生类
3.
DefaultPawnClass=class''
复制代码
DefaultPawnClas
s
绑定到我们修改的
Pawn
里,这里
不做多说明。
特别说明下
bDelayedStart
成员变量
,bDe
layedStart
来自继承的
GameInfo
类
(有兴趣的可以去
里看这个变量
调用的一些地方做了什么)
bDelayedStart
在此刻是非常重要的,
因为我
们重写
了游戏,而不是使用游戏内的
Kismet
来进行绑定,那么此时游戏内是没有
Pawn
的,我
们需要告诉引擎来调用我们的出
生类,而不是等待,那么,把
他设置成
False
,
游戏引擎将不再
等待角色的产生,
不再延迟而立即产生了我们的
Pawn
(当
然,如果你需要游戏做过场动画或
p>
者摄像机漫游的时候,以及在登陆界面的时
候
-
后面说,可以做一个方法来设置他的值将他设置为
True
)
这时候
,
我们进行调试,
可以发现我们编写的类已经全部正确调用,<
/p>
并且通过键
盘的
WSAD
键进行移动后,发现我们设置的角色已经绑定我们的摄像机一起移动
了。
第六步:
现在我们已经成功了部署整
体架构,还记得我们之前的那个
'Isometric'
吗?我
们现在就得来处理它,完成最后一步,实现自己的摄像机模式。
找到我们之前编写的
文件,对继承的
Camera
类点右键,选择转到
p>
定义。
(
或者打开
)
p>
按下键盘的
Ctrl+F
找到
UpdateViewTarget
方法,复制进我们的
因为我们要在中间部分修改,
所以不好直接调用
ViewTarget()
了。
找到
switch(
CameraStyle
)
部分,<
/p>
添加我们前面定义的那个
'Isometric'
的
case
1.
/******************************************
********************
***
2.
*
自定义摄像机模式开始
3.
**************
*************************************************<
/p>
**/
4.
//
从自定义的
Pawn
类
(KWPawn)
的
GetDefaultCameraMode
传来
5.
case
'Isometric':
6.
//
修改摄像机位置
7.
=
(-55.0f *DegToRad) * RadToUnrRot;
8.
= (0
*DegToRad) * RadToUnrRot;
9.
=
(30.0f *DegToRad) * RadToUnrRot;
10.
11.
//
修改摄像机的位置和角色的偏移
12. Loc.X = on.X - 64;
13. Loc.Y = on.Y - 64;
14. Loc.Z = on.Z + 156;
//
距离位置
15.
16. //
设置缩放
17. Pos = Loc - Vector(Rot) *
FreeCamDistance;
18. on = Pos;
19. on = Rot;
20.
break;
21./***************************
***********************************
***
22.*
自定义摄像机模式结束
<
/p>
23.*************************************
**************************
**/
复制代码
由于复制过来的代码使用了一个成员变量
=
DefaultFOV;
所以,
在
C
amera
类里,
找到赋值他的地方添加进我们重写的
KWCamera
类里。
添
加
DefaultProperties
方法。
这样方便我们以后如果对这个值进行修改而不动底
层的东西。
1.
DefaultProperties
2.
{
3.
DefaultFOV=90.f
4.
}
复制代码
/**************
**************************************************
*
*
*
UpdateViewTarget()
方法介绍
*
*
这个类继承了基类的
Camera
摄像机类
.
*
当
这
个
类
创
建
的
p>
时
候
,
则
会
自
动
调
用
基
类
GamePawn<
/p>
的
虚
方
法
GetDefaultCameraMode(
需要重载
)(ps.
其实
UE3
里<
/p>
,
没有虚函数
,
他们
extends
后
,
都属于重写
,
本身他就有这方法
,
可以进基类的
uc
文件看他怎么
写的
).
*
如
< br>果
想
自
己
创
建
新
的
摄
像
机
模
式
p>
,
则
需
要
重
载
GamePawn
的
GetDefaultCameraMode
的方法
.
* /** Camera Mode */var Name
CameraStyle;
* Camera
类
里
的
CameraStyle
成
员
变
量
,
就
是
通
过<
/p>
GamePawn
的
GetDefaul
tCameraMode
实现的。
(ps.
我觉得这个方法名用
Set
更合适,不过他
不是方法,是需要继承的,所以
Get
也没错
)
*
我
在
继
承
的
GamePa
wn
类
(KWPawn)
里
返
回
了
Isometri
c,
那
么
,
我
们
在
里,
p>
找到
UpdateViewTarget
方
法,
将其复制过来
(
其实也可以不复制
,
复制的好处是原始的摄像机模式保留
)
*
在
switch(
CameraStyle
)
的地方添
加对
Isometric
的处理(
Is
ometric
随便
定义,不过你怎么
case
的就在你定义的
Pawn
里怎
么
Get
*
在这个类里可以设置
*
这是一个可以简单使用且有品质保证的摄像机类上的基本功能,增加或者说
是扩展了另一款同等级
GameCamera
的功能
*******************************
**********************************/
我大概说下我的自定义视角里面的代码含义。
首先是
Rot
在这里我们固定摄像机角度进一个或多或少等角的固定角度之内。
(Pitch
Roll
Yaw
你可以理解为三个面的旋转方式,就类似
p>
UDK
里面的旋转三跟线)
然后是
Loc
在这里我们定义一个默认的摄像机位置距离
Pawn(
我们
的角色
)
的位置。
最后是
Pos = Loc
–
Vector(Rot) *
FreeCamDistance;
它做的是以现在的摄像机旋转作为方向矢量然后借着
FreeCamDistance
来加
大。
FreeCamDistance
在父类定义中默认值是
256.0 f
。
最后,
当我们按下
F5
进行调
试,
就可以发现我们可以通过键盘的
WSAD
< br>键来控制
角色进行行走了,并且已经固定为斜
45
度角了。
如果你想修改你的视角,那么对<
/p>
'Isometric'
里的代码进行修改。
如果你想添加多种视角,那么添加这里的
case
进行处理,然后在继承了
Pawn
类的
KWPawn
类里控制
GetDefault
CameraMode
的返回值来进行完成。
总结:
我们已经通过修改完成了使用
自己的视角来进行游戏,
在下一章节中,
我们将重
写我们的控制方法,使用鼠标来进行角色的移动。并且初步谈谈关于
HUD<
/p>
(界面
渲染)。
在前面
的教程中,我们已经把我们创建的角色放入置我们的场景之中了。
现在,我们将重写我们的控制方式,使用我们自定义的方式来控制我们的角色。
第一步:
我们先把制作好的鼠标指针模型
(可以参考其他教程或者等待其他人更新模型制
作教程,
在此系列就不涉及大部分
UDK
编辑器
部分的操作,
本系列留给程序员)
放入
KingdomWorldUTGa
meContentEffect
中。
(KingdomWor
ld
UTGameContent
后的路径随便你定义,你直
接放在
Content
里也行,这样做的
目的仅仅是便于管理而已)
附带一个我随便制作的模型:
第二步:
2.1.
< br>打开工程。在
Classes
文件夹里添加一个
KWHud
类。并编写如下代码
1.
class KWHud
extends GameHUD;
2.
3.
simulated event PostBeginPlay()
4.
{
5.
ginPlay();
6.
`Log(
界面类运行
7.
}
复制代码
我们编写了一个继承了界面类的的
类,
在这里我们可以在渲染事件里做一些东西
(比如
UI
,文字等)
2.2.
接着,我们添加一个方法
1.
function
vector2D GetMouseCoordinates()
2.
{
3.
local
Vector2D mousePos;
4.
local UIInteraction UIController;
5.
local
GameUISceneClient GameSceneClient;
6.
UIController = ontroller();
7.
if (
UIController != None)
8.
{
9.
GameSceneClient = lient;
10. if ( GameSceneClient !=
None )
11. {
12. mousePos.X =
osition.X;
13.
mousePos.Y = osition.Y;
14.
}
15. }
16.
return mousePos;
17.}
复制代码
/**************************************
****************************
*
*
GetMouseCoordinates()
方法介绍
*
*
这是我们自己定义的一个方法。
*
通过这个方法返回一个
vector2D
*
vector2D
包含了我们鼠标在当前场景中的正确位置。
*
其实就是
ontroller().osition;
******************************************
************************/
<
/p>
通过这个方法,我们可以随时取得当前鼠标的位置(在后面用到)
第三步:
找到我们之前编写的
文件
声明如下变量
1.
var Vector2D
PlayerMouse;
2.
var Vector MouseHitWorldLocation;
3.
var Vector
MouseHitWorldNormal;
4.
var Vector MousePosWorldLocation;
5.
var Vector
MousePosWorldNormal;
6.
var vector StartTrace;
7.
var Vector
EndTrace;
8.
var
vector RayDir;
9.
var Vector PawnEyeLocation;
Actor TraceActor;
复制代码
第四步:
4.1.
找到我们之前编写的
文件
声明如下变量
1.
var
FontRenderInfo TextRenderInfo;
//
一个字体渲染类,
可
以控制他修改
字体
复制代码
4.2.
添加如下方法
1.
function
DrawHUD()
2.
{
3.
//
定义一个字符串常量
4.
local
string StringMessage;
5.
6.
//
显示我们控制类的当前鼠标位置指向的何种类对象
7.
//(TraceAct
or
在
PostRender
方法中已
赋值
)
8.
if(KWPlayerController(PlayerOwner).TraceActor !=
none)
9.
{
10.
//
将类名赋值给
StringMessage
11.
//
在这里我们可以判断当前选中了何种类型的对象
12.
//
对不同的对象可以做不同的响应处理
13.
//
当然,如果鼠标点击到不同的对象,一样可以通过他取得。
14.
//
以后的教程中我们将介绍如何渲染中文字体。
15. StringMessage =
Actor:
16. }
17.
18. //
把
StringMessage
的内容渲染进
x=250,y=10
的位置
19. lor = MakeColor(255,183,11,255);
20. ( 250, 10 );
21.
xt( StringMessage, false, , , TextRenderInfo );
22.}
复制代码
/**************
**************************************************
***
*
DrawHUD()
方法介绍
*
*
自定义渲染方法,我们在这里可以渲染一切我们像要的东西。
***************************************
****************************/
4.3.
添加如下方法
1.
event
PostRender()
2.
{
3.
local KWCamera PlayerCam;
4.
local
KWPlayerController IsoPlayerController;
5.
nder();
6.
//
取得我们角色当前的控制类的指针
7.
IsoPlayerController =
KWPlayerController(PlayerOwner);
8.
//
将我们定义的
GetMouseCoordinates
方法
的返回值保存进
PlayerMouse
变量中
9.
Mouse
= GetMouseCoordinates();
10. //
这个方法可以在
类中找到。
这个方法的用途是传入一
个
2D
坐标获
得他在场景中的
3D
位置和方向。
11. ect(Mouse,
osWorldLocation,
osWorldNormal);
12.
//
去的当前空指针的摄像机指针
13. PlayerCam = KWCamera(Camera);
14. //
设置
RayDir
p>
为当前控制类的方向
15. =
osWorldNormal;
16. //
设置
StartTrace
为当前摄像机位置
p>
+100(z
轴
)
位置
+
控制类的方向
*10
17. race =
(on +
vect(0,0,100)) +
* 10;
18.
//
设置
EndTrace
为
StartTrace+
控制类的方向
*500
0(5000
是作为延伸,
够远了
)
19. ce = race
+ * 5000;
20.
//
取得当前鼠标在场景中指向的对象。
21.
//Trace
需要传入指针方向,起始位置和结束位置
22. //
之所以之前传个
*50
00
的
EndTrace
,
是为了鼠标指在模型上,
好判断
23. //
这个方法会返回一个
M
ouseHitWorldLocation
,
也就是鼠标点击
的这
个对象的
3D
位置
(
我们暂时用不到他
)
24. //
在这里我们每帧都跟踪
MouseHitWorldLocation
的世界坐标
25. //(
这里你能追踪
Actor
对象
的碰撞
,
为了这个简单教程
,
我们
没有对
结果做任何改动
,
但如果你想过
滤掉对地形的点击
26. //,
或玩家点击
npc,
你可以检查
StartFire
函数里的对象碰撞,在那
边做处理
-
后面有说
27. ctor =
Trace(itWorldLocation,
itWorldNormal,
ce, race,
true);
28.
29.
//
计算角色的视角位置为了调试光线和检查移动后的碰撞
30. eLocation =
Pawn(rget).Location +
Pawn(rget).EyeHeight * vect(0,0,1);
31. //
开始渲染我们的东西
32. DrawHUD();
33.}
复制代码
PostRender
是来自父类的方法,我们重写后,
nder();
了他,然后
我们才可以继续做
我们自己的事情,
这个方法作为渲染类,他每一帧都会执行一次。
在这里,我们主要是为了取得
TraceActor(
当前指针摸到的对象
)
,以及选择范
围
(StartTrace
,
EndT
race)
第五步:
现在,
我们已经可以把鼠标当前摸到的对象以文字的形式通过
DrawHUD
渲染进屏
幕。
但是你要说了,我调试的时候看不到我的鼠标指针啊?
别急,在下一节,我们将会让你加载一个鼠标模型,方便调试。
楼外音:“我靠,你不会就跑了吧?”
当然不是,在这里,我介绍一个简单的办法来显示鼠标位置。
主要是因为这一节太多了,我相信你也得慢慢吸收,不适合一次性讲那么多。
好。废话少说,还记得我们之前在
PostRender
类里设置进控制类里的那些变量
吗?
我们不要浪费他们。
5.1.
首先,找到我们之前编写的
文件
声明如下变量
1.
var bool
bDrawTraces; //
通过它控制是否显示鼠标
跟踪调试线。
复制代码
5.2.
添加一个方法来控制
bDra
wTraces
它的值
1.
exec function
ToggleIsometricDebug()
2.
{
3.
bDrawTraces = !bDrawTraces;
4.
if(bDrawTraces)
5.
{
6.
`Log(
显示鼠标跟踪调试线
p>
7.
}
8.
else
9.
{
10. `Log(
不显示鼠标跟踪调
试线
11. }
12.}
复制代码
/**************
**************************************************
**
*
ToggleIsometricDebug()
方法介绍
*
*
创建一个控制台命令
*
使用这个命令会开启
bDrawTraces
开
关,在
PostRender
方法中
*
在
PostRender
方法中我们将会显示当前鼠标的路径。
*
通过他我们可以显示我们的角色一个正确的行走路径。
*
*
必须用
exec
function
的声明方式
*
方法名可以任意取,你取啥名,在控制台就输啥命令
*
**************************
****************************************/
5.2.
添加一个方法来显示鼠标
1.
function
DrawTraceDebugRays()
2.
{
3.
local KWPlayerController IsoPlayerController;
4.
IsoPlayerController =
KWPlayerController(PlayerOwner);
5.
6.
//
绘画选择范围。
7.
//MakeCo
lor
的参数为
R,G,B
以及透明通
道。
8.
Draw3DLine(race,
ce,
MakeColor(255,128,128,255));
9.
//
绘画移动路线
10.
Draw3DLine(eLocation,
itWorldLocation,
MakeColor(0,200,255,255));
11.}
复制代码
/**************
**************************************************
***
*
DrawTraceDebugRays()
方法介绍
*
*
渲染显示鼠标跟踪调试线。
* <
/p>
这个方法在
PostRender
中,通
过
bDrawTraces
作为开关调用。
************************************
*******************************/
5.3.
在
PostRender
方法中,找到
DrawHUD()
方法的调用地方,在后面添加如下
代码:
1.
if(bDrawTraces)
2.
{
3.
//
父类有这么一个玩意,可以显示寻路的线路。
4.
ute(Pawn(rget));
5.
DrawTraceDebugRays();
6.
}
复制代码
第六步:
现在,我们需要绑定这个<
/p>
Hud
类。
6
.1.
首先,找到我们之前编写的
文件
在
DefaultProperti
es
里添加
一行
1.
//
设置界面类
2.
HUDType=class''
复制代码
现在,你可以调试工程,通过控制
台输入
ToggleIsometricDebug(
你可以输
入
togglei
出现全部的命令后按
tab
再按回车
,
大小写随便
)
发现鼠标移动到的位置,屏幕上就会显示你选择的是何种对象。
楼外音:“楼主你最前面发的那个资源文件是干嘛的?我没看到地方调用啊”
嗯。。。那个。你也发现了,其实这是第六步,不是总结。
<
/p>
细心的同学可能已经发现了,
那个最前面第一步发的资源其实是一
个鼠标指针的
资源。
那么,我们还是
说说怎么加载一个鼠标指针把,而不是用这两根线。
6.2.
打开工程。
在
Classes
文件夹里添加一个
MeshMouseCur
sor
类。
并编写如下
代码
1.
class
MeshMouseCursor extends Actor;
2.
var()
StaticMeshComponent Mesh;
3.
DefaultProperties
4.
{
5.
Begin Object
Class=StaticMeshComponent Name=MarkerMesh
6.
BlockActors=false
7.
CollideActors=true
8.
BlockRigidBody=false
9.
//
模型文件
10. StaticMesh=StaticMesh'0001mesh'
11. //
重置模型的大小
-
0.3
倍
12.
Scale3D=(X=0.3,Y=0.3,Z=0.3)
13.
Rotation=(Pitch=-16384, Yaw=0, Roll=0)
14. End Object
15.
Mesh=MarkerMesh
16.
CollisionComponent=MarkerMesh
17.
(MarkerMesh)
18.}
复制代码
你看到的没错,
StaticMesh'0001mesh'<
/p>
这玩意就是我最前面提
供的文件里的资源路径名。
现在,我们已经创建了一个
Actor
对象(鼠标指针),如何把他应用到游戏中去
呢
6.3.
找到我们之前编写的
文件
声明如下变量
1.
var
MeshMouseCursor MouseCursor;
//3D
鼠标指针
复制代码
6.4.
在
KWPlayerCont
roller
类的
PostBeginPlay
方法中
ginPlay();
的后面添加如下代码:<
/p>
1.
MouseCursor =
Spawn(class'MeshMouseCursor', self, 'marker');
复制代码
6.5.
添加方法
1.
event
PlayerTick( float DeltaTime )
2.
{
3.
Tick(DeltaTime);
4.
//
设置当前鼠标的位置为
KWHud
中
PostRender
方法取到的
MouseHitWorldLocation
5.
ation(MouseHitWorldLocation);
6.
}
复制代码
PlayerTick
是父类的一个方法,我们重载了它。
p>
在这里,我们没必要去调用父类的
Tic
k()
了。
他
原
本
会
通
过
PlayerTick
来
移
动
(
可
参
)
当然这些都要我们重新来做了,所以无需调用原本的过程了。
考
使用
MouseHitWorldL
ocation
是因为我们让鼠标的位置呈现三维状态,
他一直
跟
着地表(或者物体)走。
当然,你
也可以设置它为一个
2D
位置。
这时候我们调试项目,
可以发现鼠标
的指针已经跟随着我们动了,
并且显示移动
到位置的对象名
p>
楼外音:“这指针好丑啊,黑不拉几一陀”
< br>嗯。。。这位同学,这是代码教程。。。你也可以把他做成
2D
< br>的图片嘛,当然
做
3D
是为了教
程需要。
当然,
还记得我们自定义的
Pawn
类吗?你可以试着和
KWPa
wn
一样,
添加一个灯
光给他。(本文
不做说明,自己动手才有乐趣嘛,当作本节作业)
总结:
这一节主要取得了我们走路需
要的一些关键数据,
并且简单介绍了渲染的方法和
如何区别不同
对象的处理。
在下一节中,我们将会使用我们自己做的这个鼠
标,来进行走路。
在前面的教程中,我们已经将我们的鼠标指针放入场景中了
<
/p>
接下来,我们将全面接管引擎的输入。把他的控制方式交给我们来处理。
< br>
第一步:
首先我们把
添加进工程
(以添加为
链接方式,具体参考第一章第一节)
找到
[Input]
中的
Bindings=(Name=
Binding
s=(Name=
这里我特别说明一下
里,引擎会通过
他,找到相应的映射控制方
法。
Na
me=
为底层方法,这是一个鼠标滚轮移动事件。
Command=
后面这个为这个事件将会对应的控制台命令。
在这里,你可以找到一切你所需要的消息映射
,比如键盘的按键,鼠标的。以及
Xbox
360
中按键的映射。
1.1.
首先我们修改
Bindings=(Name=
Bindings=(Name=
为如下代码:
1.
Bindings=(Name=
2.
Bindings=(Name=
复制代码
他原本的鼠标滚轮事件激活
了换武器的方法,当然
UTGame
目录下的代码已经给
我们删了,这个事件是不会被调用的。
但是
这个方法名不太好看,
会造成教程的歧义。
你可以修改成自己需
要的功能方
法名,为了教程通俗易懂,我们将方法名就直接改为事件名。
1.2.
建立好映射后,
我们需要实现这个方法的功能。
找到我们之前编写的
文件
添加如下方法:
1.
//
拉近镜头
2.
exec function
MouseScrollUp()
3.
{
4.
`Log(
拉近镜头
5.
mDistance -= 64;
6.
}
7.
8.
//
拉远镜头
9.
exec function
MouseScrollDown()
10.{
11.
`Log(
拉远镜头
12.
mDistance += 64;
13.}
复制代码
还记得我们摄像机类
KWCamera
里对我们的摄像机模式
Isometric
的处理吗?
//
设置缩放
Pos = Loc - Vector(Rot) *
FreeCamDistance;
通过
MouseScrollUp
和
MouseScrollD
own
方法,
我们可以修改摄像机的缩放位置。
以
64
个大小为单位(
UDK
里一个单位为
2
厘米)
现在我们可以调试工程,试试你的鼠标滚轮,是不
是可以缩放镜头了。
第二步:
打开
找到
[Input]
中的
Binding
s=(Name=
Bindings=(Name=
修改为:<
/p>
1.
Bindings=(Name=
2.
Bindings=(Name=
复制代码
Bindings=(Na
me=
StopFire
Bindings=(Name=
p>
StopAltFire
修改为:
1.
Bindings=(Name=
| OnRelease
LeftMouseButtonUp
2.
Bindings=(Name=
wn |
OnRelease
RightMouseButtonUp
复制代码
这样做的目的是把
LeftMouseButton
的消息扩充消息,
因
为他有两个消息处理事
件,一个按下和松开的消息,用
|
分开,松开的定义为
OnRelease,
当然,你也可
以设置一个变量名来处理他,比如他之前的
But
ton bFire
,在这里我们暂时用
不到,所以去掉了它。
Bindings=(Name=
Bindings=(Name=
StopAltFire
p>
准确的说是鼠标右键绑定了
AltFire
< br>而
AltFire
有两个消息,一个是右键按下为
StartAltFire
,右键松开为
St
opAltFire
希望你能看懂这部分的修改的含义。
因为
RightMouseButton
对应的消息有子消息,所以
Cmmand
不能直接为
RightMouseButton
否则他会去代码里寻找
exec function Righ
tMouseButton
,而对应的子消息扩
展就会有问题。
所以加了一个
at
为
RightMou
seButtonAt
不然有两个
R
ightMouseButton
他不知道怎么映射了,要把
R
ightMouseButton
对应的消息名分开
而之前的那个滚轮无所谓,因为滚轮没有扩展消息。
第三步:
3.1.
找到我们之前编写的
文件
p>
声明如下变量:
1.
var bool
bLeftMousePressed;
//
判断是否按下鼠标
左键
2.
var bool
bRightMousePressed;
//
判断是否按下鼠标
右键
3.
var float
DeltaTimeAccumulated;
//
累计鼠标按下时间
复制代码
3.2.
修改
PlayerTick(
)
方法
在
a
tion(MouseHitWorldLocation);
后面增加如下代码:
1.
//
统
计左键按下去的时间,
如果你想用右键,
修改为
bRightMousePressed
2.
if(bLeftMousePressed)
3.
{
4.
//
累计鼠标按下去一共多久
.
5.
DeltaTimeAccumulated += DeltaTime;
6.
}
复制代码
3.3.
添加如下方法:
1.
//
按下鼠标左键
2.
exec function
LeftMouseButtonDown()
3.
{
4.
MouseButtonDown(0);
5.
}
6.
7.
//
松开鼠标左键
8.
exec function
LeftMouseButtonUp()
9.
{
10. MouseButtonUp(0);
11.}
12.
13.//
按下鼠标右键
function RightMouseButtonDown()
15.{
16.
MouseButtonDown(1);
17.}
18.
19.//
松开鼠标右键
function RightMouseButtonUp()
21.{
22.
MouseButtonUp(1);
23.}
24.
25.//
按下鼠标
on MouseButtonDown(byte MouseMode)
27.{
28.
//
重置按下鼠标时间
29.
DeltaTimeAccumulated = 0;
30.
31. //
判断按下了哪个键
32. bLeftMousePressed = MouseMode ==
0;
33. bRightMousePressed =
MouseMode == 1;
34.
if(bLeftMousePressed)
`Log(
按下了鼠标左键
35.
if(bRightMousePressed)
`Log(
按下了鼠标右键
36.}
37.
38.//
松开鼠标
on MouseButtonUp(byte MouseMode)
40.{
41.
`Log(
总共按下的时间:
42.
//
重置鼠标状态
43.
if(bLeftMousePressed && MouseMode == 0)
44. {
45.
bLeftMousePressed = false;
46.
`Log(
松开了鼠标左键
47.
}
48. if(bRightMousePressed &&
MouseMode == 1)
49. {
50. bRightMousePressed = false;
51.
`Log(
松开了鼠标右键
52.
}
53.
54.
//
重置鼠标按下时间
55.
DeltaTimeAccumulated = 0;
56.}
复制代码
现在,
我们可以调试一下游戏,
发现游
戏的日志窗口已经正确的捕获了我们鼠标
的左右键的功能。并且能够得到鼠标左键按下去
的时间。
第四步:
4.1.
找到我们之前编写的
文件
声明如下变量:
1.
//
计
算角色位置到
MouseHitWorldLocation
的
距离
2.
var float DistanceRemaining;
3.
//
表
明在可接受的范围目的地中,停止移动
4.
var bool
bPawnNearDestination;
复制代码
4.2.
添加一个
state
方法。代码如下
1.
state
MoveMouseClick
2.
{
3.
event PoppedState()
4.
{
5.
`Log(
通过鼠标停止移动,清除
StopLingering
计时器
6.
//
因为
通过鼠标停止了移动状态,所以要清除之前创建的计时器
7.
if(IsTimerActive(nameof(StopLingering)))
8.
{
9.
ClearTimer(nameof(StopLingering));
10.
}
11. }
12. event
PushedState()
13. {
14.
//
创建一个计时器,规定角色最长只能走三秒
15. //
这段代码没什么含义,只是初步解释一
下计时器的创建,调用,
和删除
16.
//
如果你需要它可以打开下面的注释
17. //SetTimer(3, false,
nameof(StopLingering));
18. if
(Pawn != None)
19. {
20. //
还记得我们没打开的
KWPawn
的
PhysicsAsset
吗?
21.
//
这里控制了物理包,这里是控制角色的移动的骨骼动作。
22. ementPhysics();
23. }
24. }
:
26.
while(!bPawnNearDestination)
27. {
28.
//`Log(
移动中
29.
MoveTo(GetDestinationPosition());
30.
}
31.
`Log(
已移动到目的地
32.
PopState();
33.}
复制代码
//SetTimer(3, false,
nameof(StopLingering));
这段代码我注释了,这里的意思是
说,创建一个
3
秒为单位的计时器。
3
秒后调
用
StopLingering
在
StopLingering
里,<
/p>
我们将会停止角色的行走状态,
这里只是初步的介绍一下
计时器的用法。
4
.3.
添加
StopLingering
方法,代码如下:
1.
function StopLingering()
2.
{
3.
//
停止当前所有移动状态
4.
`Log(
已移动了
3
秒,停止移动
<
/p>
5.
PopState(true);
6.
}
复制代码
另外我说下
ementPhysics();
我们可以选中
SetMovementPhysics
点击右键选择转到定义。
这个方法是引擎提供的一个播放行走骨骼动画方法。
他会判断你在水面上方还是下方,来播放
SetPhysics(PHY
S_Swimming);
还是
SetPhysics(PHY
S_Falling);
如果你有在按键要处理一些技能动作
,
或者定义你自己的物理包骨骼动画名,
那
么,直接调用
sics(
你的东东
);
4.4.
在
MoveMouseClick
状态里的
Begin
标签里,我们使用了
MoveTo
进行行走。
引擎会回调一个
< br>PlayerMove
方法给我们,我们重载他,编写如下代码:
1.
function
PlayerMove(float DeltaTime)
2.
{
3.
local
Vector PawnXYLocation;
4.
local
Vector DestinationXYLocation;
5.
local
Vector Destination;
6.
local Vector2D DistanceCheck;
7.
Move(DeltaTime);
8.
//
获得玩家距离目的地的距离
9.
Destination
= GetDestinationPosition();
10.
DistanceCheck.X = Destination.X - on.X;
11. DistanceCheck.Y = Destination.Y -
on.Y;
12. DistanceRemaining =
Sqrt((DistanceCheck.X*DistanceCheck.X) +
(DistanceCheck.Y*DistanceCheck.Y));
13.
14.
//`Log(
当前位置:
15.
//`Log(
距离位置:
16.
17. bPawnNearDestination =
DistanceRemaining < 15.0f;
18. `Log(
是否即将靠近目的地:
19.
PawnXYLocation.X = on.X;
20.
PawnXYLocation.Y = on.Y;
21.
DestinationXYLocation.X =
GetDestinationPosition().X;
22.
DestinationXYLocation.Y =
GetDestinationPosition().Y;
23.
ation(Rotator(DestinationXYLocation -
PawnXYLocation));
24.}
复制代码
第五步:
5.1.
< br>现在,我们来添加一个方法,提供一个激活我们的
MoveMouseClick
事件的
方法。代码如下:
1.
function
MovePawnToDestination()
2.
{
3.
`Log(
开始移动
4.
SetDestinationPosition(MouseHitWorldLocation);
5.
PushState('MoveMouseClick');
6.
}
复制代码
5.2.
在我们鼠标左键点击的时候,调用这个方法,我们的角
色即会行走了。
修改
MouseBu
ttonDown
方法为如下代码:
1.
//
按下鼠标
2.
function
MouseButtonDown(byte MouseMode)
3.
{
4.
//
停止当前所有移动状态
5.
PopState(true);
6.
7.
//
重置按下鼠标时间
8.
DeltaTimeAccumulated = 0;
9.
//
使用鼠标左键走路
10.
//
在里面可以通过
TraceActor
来判断点到了啥
11. //
比如点到
npc
或者其他东西不同相应的来处理
12. if(MouseMode==0)
13. {
14.
//
是否移动范围在可视范围之类
15.
if(FastTrace(MouseHitWorldLocation,
PawnEyeLocation,,
true))
16. {
17.
//
移动到点击位置
18.
MovePawnToDestination();
19. }
20. else
21. {
22. //
寻路
23. }
24. }
25. //
初始化为
false,
我们可以至少运行一次状态帧和重新计算距离
26. bPawnNearDestination = false;
27. //
判断按下了哪个键
28. bLeftMousePressed = MouseMode ==
0;
29. bRightMousePressed =
MouseMode == 1;
30.
if(bLeftMousePressed)
`Log(
按下了鼠标左键
31.
if(bRightMousePressed)
`Log(
按下了鼠标右键
32.}
复制代码
另外,
在
MouseButtonUp
中,
我们可以加上
if(
DeltaTimeAccumulated
>
0.13f)
PopState(true);
通过它来判断是否是长按键,你如果想松开鼠标就停止移动<
/p>
,
就加上他
,
附
件的
包的代码里有注解。正文不做解释。
总结:
通过调试,
我们的角色已经可以被我们的鼠标所控制了,
细心
的同学可能会发现,
寻路的那部分我注释了没写,难道没问题吗?
这是因为我们的
1001
地图没有
障碍物
(
囧
).
在后面的两节中,
我们主要说明如何
通过按住鼠标不动让角色
跟随我们行动,
以及如何使用虚幻引擎的寻路系统来穿
越障碍物
(ps:
本文花了我一天的时间构思
,
到下午的时候卡壳了,
不知道怎么继续下去了,
很多地方不知道怎么解释,
不过我的注释写的很清楚了,
还不明白的同学可以先
下载源代码看看吧,不懂的可以再这里跟帖
< br>)
英文地址
/Three/
动画系统概述
?
概述
o
管道
o
工作流程
o
带动画的网格物体
?
动画混合
o
混合树概述
o
构建混合树
?
AnimTree(
动画树
)
节点
?
混合节点
?
动画播放
o
AnimSequence(
p>
动画序列
)
o
AnimSet(
动画集
)
?
骨骼到轨迹的映射
o
AdditiveAnimati
on(
叠加型动画
)
o
AnimNodeSequenc
e(
动画节点序列
)
?
AnimNodeSequenc
e
属性
?
AnimGroups(
动画组
)
p>
?
同步
?
通知
?
组可以进行播放速度控制
设置
?
内部实现
o
根骨骼运动
?
骨骼控制器
?
物理动画
?
有用的控制台命令
?
概述
虚幻引擎动画系统为渲染的网格物体和实体添加运动效果。
带动
画的物体被称为
Skeletal
Meshes(
骨架网格物体
)
。和
Static
Meshes(
静态网格物体
)
(
它只能
通过
Matinee
进行动画
)
不同,
骨架网格物体使用一组骨骼组成一个
skeleton(
p>
骨架
)
。这些骨
骼用于驱动物体的运动及在网格物体上物体的放置位
置。
动画系统有两个主要部分
–
关键帧动画数据的播放,和动画混合。
管道
动
画系统是虚幻引擎传递途径的一部分。首先,处理一般的动画
(
混合的动画
)
。
然后应用骨骼控制器<
/p>
(
比如
Inverse
Kinematic)
。接下来是为骨架设置物理。然
后物理子系统处理剩余的物理,最后图形子系统渲染所有的物体。
工作流程
一般,
< br>程序员和动画制作人员一同工作来制作所需要的动画内容。
动画制作人员
将设置一个骨架并根据一个达成一致的惯例来为骨骼添加标签。
程序员将
基于管
道
(
类、函数、标记等
)
把所有的这些结合在一起。
带动画的网格物体
在虚幻引擎中,带动画的网格物体称为
Skeletal
Meshes(
骨架网格物体
)
p>
,因
为基于骨骼的骨架动画是用于驱动游戏中物体的动画的主要机制
。
以前,
也有基
于顶点的动画。
动画混合
虚幻引擎
3
使用
'
混合树
'
的观念来把多个动画数据
源混合到一起。
这个方法允许
您简单明了地创建一种多个动画混
合到一起的方式,
并允许您在处理的过程中很
容易地以可预测的
方式来添加更多的动画。
混合树概述
这是一个简单的动画混合树:
树是由一些树节点组成。节点主要有两类:
Blend
Nodes(
混合节点
)
(
圆
这些节点有一组子节点,并以某种方式把它们混合
形
)
到一起。
Data
Nodes(
数据节点
)
(
方
是树的叶子节点,没有子节点但实际上可以生成骨
形
)
架变换。
在这个例子中,
'Directional
< br>Blend'
节点将会基于
actors
的速度和方向来把连
接到它们的定向动画混合到一起。
这将会产生一个定向行走及跑动的动画。
然后
这些节点插入一个
'Speed-based'
中,
它
将把两个子节点基于
Actor
的速度混合
到一起。最后再将它和
Fire
混合为
'Firing-based
Blend'
。
基于几种简单在引
擎中定义的基本混合模式来创建特定的混合类型是非常容易的。<
/p>
构建混合树
动画树可以使用
AnimTree(
动画树
)
编辑器进行构建,
它是虚幻编辑器的一部分。
您可以使用通用浏览器创建一个新的
AnimTree(
< br>动画树
)
,然后双击它,便可以
打开
AnimTree(
动画树
)
p>
编辑器,并看到一颗新的空的树。
<
/p>
然后您可以在
SkeletalMeshComponent
p>
的
defaultproperties(
默认属性
)
块中告
诉它使用您的
AnimTree(
动画树
)
。
defaultproperties
{
Begin Object
Class=SkeletalMeshComponent
Name=SkeletalMeshComponent
SkeletalMesh=SkeletalMesh'rMesh'
AnimSets(0)=AnimSet'rAnims'
AnimTreeTemplate=AnimTree'rAnimTree'
End Object
}
把
AnimTree(
动画树
)
分配给
AnimTreeTemplate(
动画树模板
)
是非常重要的,而
不是分配给
Animations(
动画
)
。当动画播
放开始时
,将复制
AnimTreeTemplate(
动画树模板
p>
)
引用的
AnimTree(
动画树
)
,然后把这个实例分
配给
Animations(
动
<
/p>
画
)
,这个实例是游戏播放中真正使用的
,因为它包含着实
际的状态。
p>
AnimTree(
动画树
)
节点
AnimTree(
动画树
)
节点是建立一个新的
Anim
Tree(
动画树
)
时默认存在的节点
。
这是您连接
Animations(
动画
)
、
Blend
Nodes(
混合节点
)
及<
/p>
Morph
Nodes(
顶点变
形节点
)
的地方。您也可以在这里设置一些重
要属性。
Blend Node
s(
混合节点
)
和
AnimSequences (
动画序列
)
将会产生最终的动画。下
一步是应用骨骼控制器。
这
个工作是以单个步骤完成的,
因此骨骼的顺序很重要。
让我们设
想一下以下的情境:人物使用
IK
来移动手臂,使用程序控制
器来处理
手臂的关节。您将会想先使
IK
完成动作,然后关节完成动作,这样它可以产生
最终的姿势。为了解决这个问题,骨架
可以在三
次渲染中进行排列。
<
/p>
首先组成的骨骼
(
及它们的子节点
)
一般是
IK Bone
ComposePrePassBoneNames
链。
最后组成的骨骼
(
及它们的子节点
)
一般是<
/p>
roll
ComposePostPassBoneNames
bones(
关节
)
< br>。
混合节点
请参照
< br>动画节点
页面来获得关于虚幻引擎中的默认动画节点的更多信息。
动画播放
AnimSequence(
动画序列
)
一个
AnimSequence(
动画序列
)
是一个单独的动画,它是一个关键帧
集合,包含
着许多相关的元数据信息,比如
notifies(
通知
)
。
AnimSet(
动画集
)
一个
AnimSet
(
动画集
)
是一个
AnimSequences(
动画序列
)
的集合。它们存在于包
中,并且可以像材质、网格物体等以同样的方式在通用浏
览器中进行查看。
在一个动画集中的所有
AnimSequences(
动画系列
)
必须具有同样数量的轨迹,
并
且这些轨迹必须指向相同的骨骼。
这些应该当您在
AnimSetViewer(
动画集
)
p>
查看
器中导入一个
PSA
< br>文件时为您进行处理。
骨骼到轨迹的映射
在
AnimSet(
动画集
)
中的轨迹是通过名称和骨架网格物体中的骨骼相关联的。
这
是因
为您或许会想在骨骼数量和顺序不同的骨架网格物体上播放同样的动画
集。
要想快速地查找存储着一组
AnimSetMes
hLinkup
结构的动画集。
这些是特定
网格物体上的骨骼和
AnimSet(
动画集
)
的轨迹之间的映射
表。
A
dditiveAnimation(
叠加型动画
)
默认情况下,
AnimSequences(
动画序列
)
存储着全部的骨架动画。但
是它也可以
构建并使用叠加型动画。叠加型动画通过在
Anim
Set(
动画
集
)
编辑器中对两个
动画相减来进行构建。然后动画树再使用
几个节点把这个叠加型动画添加回去。
Additive A
nimation(
叠加型
)
动画通过
去掉冗余数据从而可以作为一种压缩方
式。
(
< br>比如:放松的走步和瞄准的走步,取出这两种走步,仅保存放松走步和瞄
准走
p>
步的不同作为一个附加部分
)
。
尽管是一个进行操作的小技巧,
但它可以在
p>
很大程度上降低所使用的动画的数量并降低所使用的内存空间。
尽管动画集查看器中动画靠它本身便可以达到很好的效果,<
/p>
但是在游戏中它需要
被添加到一个基础姿势中,从而看上去更加形
象。
您可以通过使用
AnimNod
eAdditiveBlending
节点或者仅通过在一个
A
nimNodeSlot (
动画节点元
素
)
上根据需求播放它们来添加叠加型动画。
自从
2009
年
12
月份的
QA
< br>版本开始,
Additive(
叠加
)
、
Target(
目标
)
和
Base(
基
p>
础
)
动画都保持着彼此间的引用。
在不同的动画集中
移动这些动画并维持这些引
用
(
但不是包
)
是安全的。当导入一个
Target(
目标
)
或
Base(
基础
)
姿势的更新版
本时,编
辑器将会提醒用户来重新编译相
应的叠加型动画。
如果您想更新现有数据并创建这些引用,您可以运行
FixAdditiveR
eferences
命令开关。
AnimNodeSequence(
动画节点序列
)
这是
AnimNo
de(
动画节点
)
的子类,它知道怎样
播放存储在
AnimSets(
动画集
)
中
的关键帧数据。它一般组成您的混合树的叶子节点。
您想要播放的动画序列可以通过在
Anim
NodeSequence(
动画节点序列
)
< br>中的名称
来指定。为了找到那个
AnimSequenc
e(
动画序列
)
,
它将会查找
SkeletalMeshComponen
t
中的整个
AnimSets(
动画集
)
数组。
通过名称引用动画序
列而不是通过指针进行引用的优点是:
它允许
您为完全不同的网格物体
/
动画使
用相
同的树。当搜索整个
AnimSets
数组时,它将从末端开始
并向前查找,直到
找到具有那个名称的
AnimSequen
ce
的
AnimSet
。这允许您在数
组中通过添加一
个新的具有同样名称动画序列的
AnimSet
来覆盖特定的序列。
AnimNodeSequence
属性
如果动画当前正在播放时,设置这项。如果
bPlaying
(
播放
)
当前动画暂停时,不设置这项。
如果动画应该循环并永远播放时设置这项
bLooping
(
循环
)
为真。
Rate(
速度
)
播放速度
bNoNotifies(
是否没有通知
)
如果设置这项,则不会触发动画通知。
bShowTimeLineSlider(
是否显示时
切换
拖动条来控制时间的位置。
间轴滑块
)
AnimGroups(
动画组
p>
)
当组织很多不同的动画到一起时,
p>
便需要在较高的层次上快速地组织和管理这些
动画。为了解决这个问
题,动画系统使用了
AnimGroups(
动画组
)
的概念。
通过使用
AnimGroups
,使得同步一
系列节点到一起、仅使组中最重要的节点触
发通知、
及全局地调
整所有这些节点的播放速度成为可能。
它也可以是这些选项
的组
合,不是所有的节点都需要同步。
同步
这个过程在使用一个称为
p>
AnimNodeSynch
的特殊节点前完成。
< br>这个操作自从被集
成到
AnimGroup
系统中时便已经存在。所以我们鼓励移除
AnimNodeSynch
。
动画同步背
后的原理是可以把不同长度的动画同步到一起。
这是非常有用的,
比
如,
对于运动循环。
在走动和跑动
间的无缝转换。
这个主意是为了使动画相对同
步。
比如,在整个运动循环中,左脚下降为
0%
,右脚下降为
50%
。现在,如果
我们保持走步和跑动循环相对地同步到一起,
我们便可以根据任务的速度和
任何
走步循
环的无缝变换来改变每个循环的播放速度。双脚将会被同步。
通知
当
在相似的动画间进行变换时,
也存在一个处理通知的问题。
比如
,
具有运动动
画的脚步。
当在不同循环
间变换并使用基于权重界线的系统来触发通知时,
您可
能会
p>
以根本没有触发任何通知的情况告终
(<
/p>
或者有时候,可以一次触发几个通
知
)<
/p>
。我们真正想要的是一个组中最重要的动画来负责触发通知,这也正事
AnimGroups
所做的工作。
组可以进行播放速度控制
最终,
AnimGroups
也允许在组的层
次上控制动画的播放速度。注意这是除了每
个动画节点速率之外的操作。所以动画节点可
以有不同的
/
各种各样的速度,而
组速
度将在它们独立的播放速率之上来缩放那个组中所有动画节点的速率。
设置
为
了创建一个组,请选择
AnimTree
节点
< br>(
混合树的根节点
)
。展开
p>
AnimGroups
,
并添加一个新项,
在
组名
)
属性
中为您的组输入您想使用的名称。
RateScale
属性是用
于缩放这个组的全局播放速度。
然后,选择您想添加到这个组中的
AnimNodeSequence
< br>节点。展开它的
Group
部
分
,您将会看到以下属性:
bForceAlwaysSlave
节点将会被同步,但是永远不会被选择为主要节点。
默认为真,节点将会被同步。如果您不想同步这个节点,请
bSynch
ronize
不要选中此项。
这个节点所属于的组的名称。设置它为和您在
AnimTree
SynchGroupName
AnimGroups
数组中创建的组名称一样的组。
如果
所创建动画不是和其它动画
(
左脚、反向的右脚
)
进行相
SynchPosOffset
对地同步,那么通过偏移动画来使它匹配是可能的。
Offset
(
偏移
)
是一个相对
位置,从
0.f
到
1.f
。
内部实现
分组系统,
当所有的节点被实时计算后,
在第二次中它将会强制更新组中所有的
节点。
所以在混合树中的所有节点都具有最新的权重。
< br>然后每个组将会寻找两个
主要
节点。一个用于同步,另一个用于通知。要使用
2
个主要节点的
原因是不
是所有的节点都需要被同步,
并且也不是所有的节点都
需要触发通知。
所以在每
个种类中的
主要节点都是最相关的节点
(
在树中具
有最高权重的节点,
可以活着
被同步活着触发通知
)
。
一旦选择了主要节点,
那么所有的组节点都是补充资料,
需要同步的节
点是,需要触发通知的节点也是。
在
AnimTree
中有几个有用的脚
本函数用于从脚本代码中控制组。添加
/
删除节
点、控制同步位置、播放速度缩放等。
根骨骼运动
请参照
根骨骼运动
页面。
骨骼控制器
当动画已经被提取出来
并混合到一起后,便可以应用骨骼控制器,比如
IK(
逆向
p>
运动学
)
。请查看
SkeletalControllers(
骨架控制器
)
p>
页面来获得关于这个步骤
以及您可以使用的节点类型的更多信息
p>
使用骨架控制器
。
物理动画
关于结合物理和动画的更多信息,请参照
物理动画
页面。
p>
有用的控制台命令
show
bones
-
显示用于渲染骨架网格物体的骨骼的位置。
虚幻引擎中的包
?
?
?
?
?
?
?
?
?
简介
包类型
组
命名
组织结构
限制
管理
加载
创建新的包类型
(
写给编程人员
)
简介
虚幻引擎中
包
的概念是一个包含一些可以通过虚
幻引擎进行操作和访问的二
进制数据的文件。
内容包含有各种类型的游戏资源。
这
些资源包括贴图、
静态网格物体、
骨架网格
物体、物理资源、
UI
Scenes
等等!任何添加到游戏引擎中的东西都可以放入到
一个包中。
使用虚幻编辑器中的
内容浏览器
,
您
可以把资源导入到包中,
到处移
动资源、重命名资源以及再次把
最终的包导出等等。
关卡是作为
一种特殊类型的包出现的。
关卡一般不包含资源。
相反,
它包含着到
包文件内的资源的引用。
这允许多
个关卡来共享资源,
并允许美术工作人员仅需
将包
文件中的资源改变一次,所有引用该资源的关卡将会自动地进行更新。把<
/p>
资源直接插入到您的关卡文件中是可能的;
但是一般不建议这样操
作,
因为它会
加大您关卡
文件的大小,同时也消除了其它关卡可以共享那个资源的可能性。
关卡也可
以充分地利用在
UnrealScript
类中定义的
Actors
。
<
/p>
UnrealScript
类被编译为单独的包。
UnrealScript
包也可以包含到内容及关卡
包中的引用。
包类型
包可以有不同的扩展名,
但是它们在内部是完全一致的。
虚幻引
擎只关心包中的
内容,
而不包含任何处理特定扩展名的特殊情况
。
然而,
有一个大多数授权用户
都会遵
守的通用习惯:
扩展
包含内容
名
编译过的
UnrealScript
代码。这些文件由
UCC
编译器生成,它们不包含
U
任何资源;仅包含引用。
关卡的默认
扩展名;包含着在编译后的脚本包中定义的
Actors
和存储在
UDK
内容包中的资源。
UPK
是包含着各种资源的内容包的通用扩展名。
授权用户可以在授权用户文件扩展名
?
页面注册唯一的关卡扩展名。
组
<
/p>
包可以包含多层的组。
可以把它们想象成您硬盘上文件结构中的子
目录。
这些组
的使用完全是为了使人们可以搞清包内容的意思;
引擎不会关心您是否使用这些
组。
<
/p>
虚幻引擎支持多层次的组结构;但是,尽管您可以按照您的意愿设计组层
< br>次的深度,
但通常推荐最多建立
3
或
4
层。
否则,
当使用内容浏览器包的树结构
时,它将会
变得特别不实用。以下是使用多个组来组织装甲资源的例子:
这个例子中的包是
Pickups
(
可能在硬盘的
包中
)
p>
。
在那个包内可
能有很多组用于组织它内部
的资源。
比如,
假设这个选中的像,
获
得指定资源的
路径将
是
als
。这
类似于
访问
您的硬
盘
< br>(
也就
是:
。每个组都可以包含资源,就像那个任何目录
可以包含文件一样。
< br>
命名
当
命名您的资源和包时,
我们强烈推荐您为它们使用唯一的名称。
把多个东西命
名为同一个名称有时会导致引擎不能精确地决定您所要加载或者引用的资源
,
从
而可
找
到了一个错误资源。这样导致的一些难以发现的问题,并且这些问题很
难调试解决。
p>
所以只要直接彻底地避免这样的问题,
为
您的
资源
/
包
<
/p>
进行唯一
的命名。已经说过,组的名称可以是您想象的任何东西。
它们不需要是唯一的,
因为它们永远不会被直接地引用或搜索。
组织结构
内容包一般存储在您的软件版本的
C
ontent(
内容
)
目录内。
它们可以包含代表各
种类型内容比如贴图或
U
I
Scenes
的子目录。再次说明,这仅是为了更有利于人
类的可读性和可维护性。
关卡包存储
在您的软件版本中的
Maps
目录中。
编译完成的
UnrealScript
包存储在您的软件的
Scripts(
脚本
)
目录中。
限制
对于一个包文件中可以出现的
资源的数量没有限制,
但是对于整个包的大小的限
制为
2GB
。
超出这个限制将会导致包不能在某些平
台上加载。
如果包已经接近
2G
的一半
,
那么尝试把包中的各个部分抽出来并分为多个较小的包是一种明智的做
法。
管理
另
外,
如果包中包含着不同团队人员使用的各种类型的内容,
那么
包可能会变得
很大。这样在
Source Control(<
/p>
代码控制
)
中为了存储每个修订本将会创
建一个
非常大的文件拷贝。
为了避免这些问题,
可以考虑一个策略:
您扫描查看您所拥
有的一组包文件
,
并识别出大于
200-300 <
/p>
megs
的包。取出这些较大的包,并把
它们分裂开为较小的包。这可以在磁盘应用方面提供很多帮助。
烘焙将会做很多工作,
来把所有需要
的数据
组合
到
seek-free(
不用寻道
)
p>
的包
中。另外,当只有较少的内容循环的时候,稍后仅在设备循环中
把包结
合回较
大的包中是非常容易的
。
为了完成这个工作,
简单地把来自一个包中的资源重命
名为另一个。
这将会创建一个指向新位置的重定向物体。
您不能删除旧的
(
空
p>
的
)
包,
直到您已
经运行了
FixupRedirects
命令行开关来把所有
到旧的内容位置的
引用重新映射指向新的位置为止。
加载
加
载
Native
包
,
以
便
包
中
定
义
的
可
以<
/p>
影
响
native
C++
类
(
通
过
defaultproperties)
的任何数据都可以在运行代码时被应用。有一些类定义在
C++
和脚本中,它们需要保持同步。
包加载是一个非常复杂的系统,
事实上大多数授权用户都不需要在底层上对其
进
行处理。
Exports (
导出
)
是存在于包中的物体。
Imports(
导入
)
是到其它包中的物体的引用。
<
/p>
所以,如果您在包A中有一个材质
MatX
,并且它引用包
A
中的
TexY
p>
和包
B
中的
Tex
Z
,那么您将会有:
包
A:
Exports:
MatX
TexY
Imports:
包
B:
Exports:
TexZ
编
p>
辑
器
加
载
native
脚
本
包<
/p>
,
即
列
在
配
置
文
件
的
EditPackages
和
PackagesToBeFullyLoadedAtStartup
关键字中的包及它们的所有引用。
当您加载一个包
(
编辑器或游戏
)
,它将会从其它包中加载物体来解决所有的引
用。
它将
不会
加载被引用包中的所有物体。<
/p>
它仅从其它包中加载所需的少量物
体。
在编辑器中,
内容浏览器中所列出的
呈现为灰色的包进加载了一部分资源,
因为
它们是由于加载其它
包而加载的。
您可以右击这个包来完全加载它。
每次您启动
p>
编辑器将会自动扫描您的游戏的内容目录来获得包。
任何找到的包将
会显示在内
容浏览器的包的树结构中。
通过点击内容浏览器左下角的文件夹图标,您可以加载外部包
(
不是在引擎的搜
索路径之内能找到的
包
)
。然而,我们强烈推荐您不要在关卡中引用外部包或者
p>
其它包的任何资源,因为这些资源在运行游戏或者命令开关时不能找到。
?
虚幻引擎
EXEC
命令
o
概览
?
在游戏中的按键设置
通用
渲染控制
分析
/
优化
游戏设置
调试
o
命令列表
?
?
?
?
?
概览
Exec
的命令是基于字符串的命令,
您可以在游戏或编辑器中运行。
他们也被称为控制台命令
p>
,因为它们通常在一个控制台窗口中运
行。
要在游戏中执行命令,按
Tab
或<
/p>
?
,弹出控制台,键入命令,然
后按
p>
Enter
。这些命令不区分大小写。
要在编辑器中执行命令,
可在主编辑器窗口的左下方文本框中,
或
在通用浏览器的日志选项卡底部的文本框中输入命令。
在游戏中的按键设置
在某些情况下
,
EXEC
命令可以绑定到配置文件里的输入键。
输入是通过不同的
C++ exec()
实现的,通常用
ULocalPlayer::Exec()
开始。
命令列表
通用
open mapname
-
打开指定名称的地图(不加地图扩展名)。
openmenu scenename -
打开指定名称的场景并显示
( UIScene'
注意
:如果场景名不正确,请
尝试用
(包括引号)
setbind
keyname
command
-
将指定的按键名
绑定到给定的控制台
命令。
shot -
根据屏幕的分辨率(或窗口分辨率,如果游戏在
窗口模式
下运行)截图。
tiledshot resolutionscale pixeloverlap
- A high resolution
is screenshot is
taken at the given scale of the current
resolution, with a pixel overlap for
each tile.
指定比例的高分辨率截图。
togglescreenshotmode -
截屏时显示或隐藏用户界面。
渲染控制
FREEZERENDERING - This will
freeze/unfreeze the set of
rendered
actors.
当你第一次冻结,系统会记住当前渲染对象。然后,当你解冻时,
p>
只有这些对象将被渲染。
所以,
你可以跑来
跑去,
打开线框模式等,
您将只能看到被冻结的对象。
注:在编辑器中,只会冻结透视图。
FREEZESTREAMING - This will
freeze/unfreeze the level
streaming and
visibility.
当您解冻,本应被加载的关卡将继续加载。
Note that this does nothing in the
editor viewports, as it
already has the
Level Streaming Previs button (and simply
turning
off
the
Previs
will
leave
the
visible
levels
alone).
FREEZEALL -
同时执行
F
REEZERENDERING
和
FREEZESTREAMI
NG
。
RECOMPILESHADERS -
重新编译着色。
TOGGLEBPCF - Switches between Uniform
PCF and Branching PCF
shadow projection
implementations.
游戏
addbots
numbots -
添加指定数目的机器人到当前关卡
summon -
添加一个角色
giveweapon -
给玩家一特定的武器
god
–
god mode :
无敌
loaded
–
所有武器和弹药
fly
–
空中飞行
ghost
–
穿墙飞
walk
–
飞行时用该指令恢复正常
调试
set class
property value -
设置类的属性值
-
p>
设置指定的类的
所有实例的属性为以特定值。
getall
class
property
-
输出指定类的
所有实例的属性值到控制
台和日志。
getallstate
class
-
输出指定类的所有实例的状态到控制台和日
志。
displayall /
displayallstate -
同为“getall”,但在屏幕上
实时输出,类似
stats
。
display object property -
显示指定的单个对象的属性。
displayclear -
清除所有输出。
简介
?
使用材质表达式
o
打开材质编辑器
?
材质编辑器概述
o
材质编辑器布局
o
菜单条
?
窗口
o
工具栏
?
预览面板
o
属性面板
?
材质
?
应用
?
材质实例
?
对象
o
材质表达式面板
o
材质表达式图表面板
o
控制
?
鼠标控制
?
键盘控制
?
热键
?
使用材质进行工作
o
表达式注释
o
表达式预览
?
材质参考
o
Material
Properties (
材质属性
)
?
PhysMaterial
(
物理材质
)
?
OpacityMaskClip
Value(
不透明蒙板剪切值
)
?
BlendMode(
混合模式
)
?
光照模型
?
TwoSided(
双面
)
?
线框
?
半透明
?
bDisableDepthTe
st(
禁用深度测试
)
?
bAllowFog(
允许雾
)
?
bUseOneLayerDis
tortion(
使用一个层变形
)
?
FallbackMateria
l(
后备材质
)
o
应用
?
bUsedAsLightFun
ction(
是否用作为光照函数
)
?
bUsedAsSpecialEngineMaterial
?
bUsedWithSkelet
alMesh(
是否和骨架网格物体一同使用
)
?
bUsedWith
ParticleSystem(
是否和粒子系统一同使用
)<
/p>
o
要想打开材质编辑器,可以在
Generic
Browser(
通用浏览器
)
中双
击一个材质。编辑器被分为
5
个
部分,如下所示:
菜单条和工具
可视化和导航工具
栏
2
预览面板
在静态网格物体上的预览材质。
3
属性面板
材质或选中的材质表达式节点的属性。
材质表达式列
4
一系列可用的材质表达式。
表
材质表达式图
材质表达式在这个面板中连接在一起来创建着色
5
表
器指令。
1
菜单条
Properties(
属性
):
p>
显示属性面板。
Preview(
预览
):
显示预览面板。
Material
Expressions(
材质表达式
):
显示材质表达式图表。
工具栏
以下是关于工具栏中每个按钮的描述,
正如它们在工具条中出现
的
顺序一样从左到右开始介绍。
?
图标
名
描述
称
初
移动材
质表达式,使基础
始
材质节点出现在主要面板
< br>位
的左上角。
置
切
换
p>
切换在材质预览面板中的
网
背景网格。
p>
格
预
览
选择标准的形状用于预览
形
< br>您的材质。
状
选
择
预
从当前加载的静态网
格物
览
体下拉列表中选择一个用
网
于预览的网格物体。
格
物
体
p>
使
用
在
通
用
浏
览
在通用浏览器中
选中一个
器
静态网格物体,并按下这
中
个按钮来使选中的网格物
选
体作为预览
网格物体。
中
的
静
态
网
格
物
-
-
-
-
-
-
-
-
-
上一篇:Unity3D Shader入门指南
下一篇:steam控制台