好友
阅读权限20
听众
最后登录1970-1-1
|
本帖最后由 play.1122 于 2019-12-29 11:42 编辑
使用unity3D制作逃脱类小游戏的完整思路游戏过程
读贴温馨提醒:(预计读贴需20分钟)
1.本人刚刚接触这个方面,小白一枚,大神不喜勿喷。
2.本帖使用语言全部使用C#。
3.此游戏非完全原创,非商用。
废话篇:最近快放假了,结果学校还要实训,我就选了unity3D,结果发现挺有意思,这个上手快,大家都知道unity支持java和C#两种语言,但在其更高版更趋向于C#,还有一个原因
,就是我的Java学的(此处省略好多字),这个unity3D项目是比较综合的,比较适合和我一样的小白入门。这里面用到的unity的功能比较多,而且游戏音效,特效,动画,特殊脚本
都提供好了,你可以做拆分再重组。反正目的就是让自己明白unity的属性,功能。还有就是其实我不是新成员,早就有号了,之前我经常分享破解软件,然后说我打广告,
就关小黑屋了,所以我洗心革面。(注:有人可能有错误认识,认为做游戏的所有素材都需要自己准备,当然身为个体是这样,
但在公司里游戏音效,特效,动画都是由其他专人提供给你的。)
这里我给大家提供了完整所有的资源包,并非打包好的exe,但可以直接使用。在unity打开自取,兄弟们读贴十分钟,写贴一小时,希望不要吝啬。管理员明鉴只发了素材。
正式开始
(一)创建主场景1)新建场景并保持,场景名MyStealth。
2)导入资源,拖拽Stealth.unitypackage包到Project面板。
3)过滤资源,删除没有用的目录。Prefabs(预制体),Done(官方实例),Scenes(场景目录)。
4)创建主场景游戏对象:env_stealth_static组件,为此对象添加MeshCollider碰撞器组件,过滤网格env_stealth_collision。
5)拖拽模型(汽车),摆放到对应位置,为其添加BoxCollider组件。
(二)创建警报灯光1)添加平行光源,命名为“AlarmLight”。
2)设置AlarmLight光源颜色为红色,同时设置其光照强度(Intensity)为0.
3)向光源添加脚本组件,“AlarmLight”,其原理为在0-2的光照强度来回切换,其核心代码为:
//如果当前光强强度到达了目标括光强,需要切换目标括
if (Mathf.Abs (targetIntensity - alarmLight.intensity)< 0.05f) {
//如果当獭前目标括是高光强
if(targetIntensity == highIntensity) {
//切换目标括为低台光强?
targetIntensity = lowIntensity; }
else{ //否则切换目标括为高光强
targetIntensity =highIntensity;
}
}
(三)创建警报声音
1)选中场景中的一个喇叭游戏对象(共6个),从层级视图选中全部。
2)为6个喇叭添加AuidoSource组件,Audioclip选择alarm_Triggered.
3)将AudioSource组件设置为循环播放(Loop=true),初始音量为0,并一直播放。
4)调整声音类型,为3D声音,最大范围为10.
5)将6个喇叭的Tag值,设置为Siren
(四)创建游戏对象控制器1)创建空游戏对象,命名为GameManager,设置其tag为GameClintroller
2)在GameManager身上,添加AuidoSource组件,其音频片段选择,循环播放,初始值为1.
3)为游戏控制器,LastPlayerSighting添加脚本和hashids脚本
4)在GameManager对象下,创建名为PaniMusic的游戏对象,播放警报音乐,音频片段选择PanicMusic,循环播放,初始音量为,2D声音。
5)LastPlayerSighting的核心思想是:警报位置一旦不等于(1000,1000,1000)时,警报触发,反之警报解除。
代码如下:
//解除警报馈
if(alarmPosition == normalPosition) {
//关闭警报馈灯
alarmLight.alarmOn = false;
//渐渐关闭警ˉ报馈背景音乐?
panicAudio.volume = Mathf.Lerp (panicAudio.volume,
0, Time.deltaTime* turnSpeed);
//逐个渐渐关闭警报喇叭声音
for (int i = 0; i < alarmAudios.Length; i++) {
alarmAudios .volume = Mathf.Lerp (alarmAudios .volume,
0, Time.deltaTime* turnSpeed); }
//渐渐开启主背景音乐
mainAudio.volume = Mathf.Lerp (mainAudio.volume,
1, Time.deltaTime* turnSpeed); }
//开启警报馈 else {
//开启警报馈灯
alarmLight.alarmOn = true;
//渐渐关闭主背景音乐
mainAudio.volume = Mathf.Lerp (mainAudio.volume,
0, Time.deltaTime* turnSpeed);
//渐渐开启警报背景音乐
panicAudio.volume = Mathf.Lerp (panicAudio.volume,
1,Time.deltaTime * turnSpeed);
//渐渐开启警报喇叭声音?
for (int i = 0; i < alarmAudios.Length; i++) {
alarmAudios .volume = Mathf.Lerp (alarmAudios .volume,
1, Time.deltaTime* turnSpeed);
}
}
}
(五)创建激光栅栏
1)在层级视图中,创建空游戏对象”Lasers”,作为激光栅栏的父对象
2)从Models目录下,选择fx_lasersFence_lasers模型,拖拽到场景中,依次将6个激光栅栏放到相应位置
3)选中6个激光栅栏,添加Light组件,营造红光氛围,Light组件设为点光源,Range=5,Intensity=1.5,Color=red。
4)选中6个激光栅栏,添加AudioSource组件,发出激光轰鸣声。AudioSource组件音频判断为“laser_hum”,初始播放,循环播放,初始音量为1,范围为1-5.
5)选中6个激光栅栏,添加BoxCollider组件,并且设置为触发器(Trigger)。
6)选中6个激光栅栏,添加脚本组件LaserController,将其中两个激光的闪烁标记打开。脚本逻辑为:检测玩家进入触发区域,修改PlayerLastSighting
核心脚本如下:void OnTriggerEnter (Collider other)
{ //如果是玩家
if (other.tag == Tags.Player) {
//将玩家位置同步到警报位置
lastPlayerSighting.alarmPosition
=other.transform.position;
}
}效果如图:
注意设置参数
:
(六)创建激光开关(小电脑)
1)在层级视图中,创建空游戏对象作为激光开关的父物体。
2)在Models目录下,选择模型,拖拽到场景中,放到合适位置
3)为父物体添加一个碰撞器BoxCollider,防止人物穿模,不用设置大小。
4)在父物体上,添加AudioSource组件,播放激光解锁的声音,音频片段选择“Switch_deativation,初始不播放,不循环,音量为1,2d音效。
5)在子物体身上,添加一个BoxCollider,设置为触发器,作为检测玩家靠近的触发器区域,调整其大小,如图(waibu边框是触发器)
6)在子物体身上添加LaserSwitchDeativation脚本,该脚本检测玩家是否按下了Z键,如果在触发区域按下了Z,则会解锁对应的激光,并且修改屏幕材质,
其原理是将对应的激光失去激活,
代码如下:void OnTriggerStay (Collider other)
{ //当玩家按下Z键
if (Input.GetKeyDown (KeyCode.Z) &&
other.tag == Tags.Player &&
controlledLaser.activeSelf) {
//关闭激光
controlledLaser.SetActive(false);
//切换屏幕材质
GetComponent<MeshRenderer>().material = unlockMat;
//播放声音
GetComponent<AudioSource>().Play ();
} }
(七)创建自动门1)在层级视图中创建空游戏对象“Doors”,作为三扇门的父物体。从Models目录下,查找“door_generic_slide”模型,拖拽到Doors下。
摆放好三扇门的位置。
2)选择三扇门,添加球形碰撞器组件(SphereCollider),将碰撞器改为触发器,高度设置为1,半径设置为1.5.
3)选中三扇门,添加AuidoSources组件,播放开门声音。音频片段设置为“Door-open‘,初始不播放,不循环。3D声音,范围1-5.
4)选中三扇门,添加脚本组件“Door Animation“,不勾选Needkey。
5)选中三扇门,动画控制器选择“DoorAnimationContoller“。
6)为了不允许玩家从门上穿过,在门的自物体上添加BoxCollider,无需设置大小和位置。效果如图
:
脚本逻辑是,玩家是否进入区域,区域人数不为0,则门打开,否则门关闭。
代码如下: void OnTriggerEnter (Collider other) {
//如果进来的是玩家或机器人
if (other.tag == Tags.Player ||
(other.tag == Tags.Enemy &&
other.GetType () == typeof(CapsuleCollider))) {
//人数递增 count++;
//如果是玩家
if (other.tag == Tags.Player) {
//设置玩家进入的标志位
playerIn= true;
//如果玩家没有钥匙
if (!playerInventory.hasKey &&needKey) {
//播放拒绝声音
AudioSource.PlayClipAtPoint(refuseAud, transform.position);
}
} }
}
(八)创建逃离大红门
1)从Models目录下,选择“Door-exit-outer“,拖拽到Doors对象下,摆放好位置。
2)选中红门,添加球形碰撞器,将其设置为触发器,位置为1,半径为2.
3)选中红门,添加Audio组件,音频片段选择,初始不播放,不循环,音量为1,3D声音,范围1-5.
4)选中红门,添加DoorAnimation脚本,勾选Needkey,并设置RefuseAud为“door_accessDenied”。
5)选中红门,为Animator组件设置动画状态机为“BigredAnimatorController”。
6)选中红门,的两个子物体,添加BoxCollider组件,防止玩家穿过。
(九)创建CCTV摄像头
1)创建空物体,,命名为“CCTV”,用来监视摄像头物体。
2)从Models目录下,寻找模型“prop_cctvCam”,拖拽至正确位置
3)向摄像头最底层的对象(body)添加一个空物体“trigger”。body和Trigger各自围绕x轴旋转30度。
4)在Trigger对象添加Light组件,灯光类型使用(spot)。Range=40-60,color=red,intensity=5-10,shezhiCookie的图片为“fx_cameraView_alp”。
5)在Trigger对象添加MeshCollider组件,mesh网格选择“prop_cctvCam_collision”,并勾选触发器。选择第二层游戏对象“prop_cctvCam_collision”,并勾选触发器
6)选择第二层游戏对象“prop_cctvCam_joint”,为其添加组件“Animation”,动画片段选择“CCTVCamAnimation”,使其左右旋转起来。
7)向Tirgger游戏对象,添加CCTVPlayerDetection脚本,逻辑是玩家进入触发范围,打开警报。
代码如下:void OnTriggerEnter (Collider other) {
//如果是玩家,同步警报位置
if (other.tag == Tags.Player) {
lastPlayerSighting.alarmPosition
=other.transform.position;
}
}
(十)创建自动升降电梯
1)从Models目录下,寻找电梯模型“”Prop_lift_exit拖拽到场景中
2)分析层级关系,为第二层“Door_exit_inner”层,添加脚本,使电梯的栅栏门与大红门同步打开,脚本逻辑是让栅栏门与大红门的本地坐标相等,
代码如下:void Update () {
//左右里门同步左右外门
innerleft.localPosition=
new Vector3 (innerleft.localPosition.x,
innerleft.localPosition.y,
outterleft.localPosition.z);
innerright.localPosition=
new Vector3 (innerright.localPosition.x,
innerright.localPosition.y,
outterright.localPosition.z);
}
3)在电梯对象的第三层“Prop_lift_exit_carriage”,添加AudioSource组件,播放电梯上升声音,音频片段选择,2D声音,初始不播放,不循环。
4)在prop_lift_exit_carriage对象下,继续添加boxCollider组件,将其设置为触发器,大小与电梯机箱一般大,用作检测玩家是否进入了电梯。
5)继续在prop_lift_exit_carriage电梯井添加BoxCollider碰撞器,共4个,调整其位置和大小分别是电梯的三面墙壁和地板
6)在电梯身上添加脚本组件“LiftDoorsTracking.cs”,,控制电梯的上升和重新开始游戏,
代码如下:
void OnTriggerStay (Collider other){
if (other.tag == Tags.Player) {
timer += Time.deltaTime;
//到达上升时间
if (timer > waitTime) {
//播放电梯声音
if (!liftRaise.isPlaying) {
liftRaise.Play (); }
//播放结束游戏声音
if (!endGame.isPlaying) {
endGame.Play (); }
//电梯上升
transform.root.position += Vector3.up * Time.deltaTime * moveSpeed;
//人物上升
player.position += Vector3.up * Time.deltaTime * moveSpeed;
if (timer > waitTime + moveTime) {
///TODO:重启游戏
SceneManager.LoadScene ("Stealth");
}
} }
(十一)创建卡片
1)从Models目录下,选择“Prop-keycard”模型,拖拽到游戏场景,摆放到合适位置
2)在卡片上添加light组件,color=blue,光照强度intensity=1,range=5。
3)在卡片游戏对象上添加SphereCollider,设置成触发器,y=1,半径=1.
4)在卡片游戏对象身上,添加脚本组件“卡片旋转。Cs,控制卡片旋转,代码如下:
private void Update()
{
transform.Rotate(Vector3.up* Time.deltaTime * 180);
}
5)在卡片对象身上,添加脚本组件“KeyPickUp.cs”,拾起卡片的音频片段选择“keycard_pickUp”。该脚本设置玩家拿到钥匙,并且播放拾起声音、
控制卡片消失。代码为:
void OnTriggerEnter (Collider other)
{
if (other.tag == Tags.Player) {
//更换标志位,玩家获取到了钥匙
playerInventory.hasKey= true;
//播放声音
AudioSource.PlayClipAtPoint(pickAud, transform.position);
//销毁自己 Destroy(gameObject);
} }
(十二)创建玩家人物
1) 从Models目录下,寻找玩家模型“char_ethan”拖拽到场景中。删除场景中原来的白模cube。
2) 在人物的Aniamtor组件中,设置为,动画状态机内衣3个动画片段,分别是Idle,Run,Sneak(潜行),
如图:
3) 在player身上添加刚体组件,打开重力,冻结由于重力产生在x轴三个方向的旋转,冻结在y轴的偏移。
4) 微任务添加一个胶囊体碰撞器,调整至合适位置
5) 为人物添加AudioSource组件,用于播放脚步声,音频片段选择“Play_footsteps”,初始不播放,但循环,2D音效,音量为1.。
6) 为人物添加“Playerinventory.cs脚本组件,该组件使用bool类型变量表示是否拿到钥匙,代码如下://玩家是否拥有钥匙 public bool hasKey = false;
7) 为人物添加耳朵组件,Audiolistener。
8) 为人物添加脚本组件PlayMovement.cs脚本,为脚本控制人物移动,逻辑规则是w向北s向南,a向西,d向东。
代码如下:
void Update () {
if (playerHealth.health > 0) {
//获取用户的按键情况
hor= Input.GetAxis ("Horizontal");
ver= Input.GetAxis ("Vertical");
}else { hor= 0;
ver= 0; }
if (Input.GetKey (KeyCode.LeftShift)) {
sneak= true;
}else {
sneak= false;
}
//设置潜行参数
ani.SetBool(HashIDs.Sneak, sneak);
//如果用户按下了方向键
if (hor != 0 || ver != 0) { //动画参数Speed渐变到5.5(奔跑动画)
ani.SetFloat(HashIDs.Speed, 5.5f, 0.1f, Time.deltaTime); //玩家转向
TurnDir(hor, ver); }
else { //立刻停下来
ani.SetFloat(HashIDs.Speed, 0); } //执行脚步声控制
FootSteps();
}
9) 为玩家添加脚本组件“pleyerHealth.cs”,用来控制玩家的血量和死亡,其逻辑是玩家受到攻击,血量减少,当血量小于等于0时,
人物死亡,播放结束音乐“endgame”,游戏重新开始。其核心代码如下:
void Update () { //如果血量小于等于0,死亡
if (health <= 0 && !isdead) {
ani.SetTrigger(HashIDs.Dead);
isdead= true;
}else if (isdead && !endGame) {
//开启结束游戏协程
StartCoroutine(EndGame ());
endGame= true; }
} IEnumeratorEndGame () { //播放结束音效
AudioSource.PlayClipAtPoint(endGameAud, transform.position); //等待4.4秒
yield return new WaitForSeconds (4.4f);
//重新加载场景
SceneManager.LoadScene("Stealth");
}
8)人物完成效果如下:
(十三)添加相机1)调整相机视角45度,上帝视角。
2)在相机上添加脚本组件“CameraNovement.cs”,其原理是由相机每一帧向玩家发射射线,如果射线检测到玩家以外的物体,说明玩家和相机之间有障碍物,
相机便会向头顶方向移动,直到相机坚持到玩家,相机停下来,拍玩家,
原理如图:
代码如下:void LateUpdate () { //第一个点
Vector3startPoint = player.position - direction; //最后一个点
Vector3endPoint = player.position + Vector3.up * distance;
//第二个点
currentPoints[1] = Vector3.Lerp (startPoint, endPoint, 0.25f); //第三个点
currentPoints[2] = Vector3.Lerp (startPoint, endPoint, 0.5f); //第四个点
currentPoints[3] = Vector3.Lerp (startPoint, endPoint, 0.75f); //放到数组里
currentPoints[0] = startPoint; currentPoints[4] = endPoint; //创建一个点,用来存储选择好可以看到玩家的点
Vector3viewPosition = currentPoints [0]; //遍历五点
for (int i = 0; i < 5; i++) {
if (CheckView (currentPoints )) {
//更新合适的点
viewPosition= currentPoints ;
break; } }
//摄像机移动到指定点
transform.position= Vector3.Lerp (transform.position,
viewPosition,Time.deltaTime * moveSpeed); //执行平滑旋转
SmoothRotate();
}
(十四)添加机器人AI(这是这里面最难理解的,你应该明白unity里导航的概念,不懂先查查看)
1)在Models目录下,选择机器人守卫模型“char_robotGuard”,拖拽至场景中,白放到合适位置。
2)为机器人守卫设置巡逻点,使用空物体表示,设置其在场景的显示标签为“wayPoint(小旗子)
3)机器人守卫的动画状态机选择“EnemyAnimatorController”。。该动画状态机中分为移动层和射击层,使用动画遮罩进行区分,
移动层使用了融合数值术,融合了21个动画。
4)为机器人守卫添加胶囊体碰撞器,调整大小。
5)为机器人守卫廷加球形碰撞器,设置为触发器,半径大小为10,当作机器人的感知范围,玩家进入到这个触发器范围,才能被看到或者听到脚步声。
6)为机器人守卫添加导航代{过}{滤}理组件,并设置导航。
(1地形勾选静态(static))(2)dakaiNavgation选项卡,点击bake按钮。(3)机器人守卫添加NavMeshAgent组件
7)为机器人守卫添加“EnemySight.cs”脚本。该脚本实现了机器人的“视觉”,和“听觉”功能。
(1)视觉:当玩家进入了机器人的触发器,如果玩家在机器人的视野范围呢110°之内,视为“发现”玩家,之后拉响警报,并且通知其它守卫。
②听觉:当玩家进入机器人触发器,发出脚步声音后,奔跑到发出声音的位置去“看一看”,跑的过程如果“看到”玩家,就拉响警报。
示例代码如下:void OnTriggerStay (Collider other)
{ //如果是玩家
if (other.tag == Tags.Player) { //重置
playerInSight= false; //玩家与机器人的距离
float distance = Vector3.Distance(other.transform.position,
transform.position);
//玩家与机器人之间的方向向量
Vector3dir = other.transform.position - transform.position;
//计算机器人自身前方与方向向量之间的夹角
float angular = Vector3.Angle (dir,transform.forward);
//满足视野范围内和距离范围内
if (distance < distanceOfView &&angular < fieldOfView /
2) {
if (Physics.Raycast (transform.position +Vector3.up * 1.7f,
dir, out hit)) {
if (hit.collider.tag == Tags.Player) {
//可以看到玩家
playerInSight= true;
//报警
lastPlayerSighting.alarmPosition=
other.transform.position;
}
} }
//听觉:如果机器人与玩家的导航路程在听觉路程范围内
if (EnemyListening(other.transform.position)) { //如果玩家发出了声音
if (other.GetComponent<AudioSource>().isPlaying) {
//赋值私人警报位置
personalAlarmPosition= other.transform.position;
}
} }
} /// <summary> /// 机器人与玩家的导航距离在听觉范围内
/// </summary> bool EnemyListening (Vector3 playerPos) {
UnityEngine.AI.NavMeshPathpath = new UnityEngine.AI.NavMeshPath (); //如果导航可以到达玩家位置
if (nav.CalculatePath (playerPos, path)) { //用数组获取所有的路径点
Vector3[]points = new Vector3[path.corners.Length + 2]; //起点
points[0] = transform.position; //终点
points[points.Length - 1] = playerPos; //赋值中间的拐点
for (int i = 1; i < points.Length - 1; i++) {
points = path.corners [i - 1]; } //导航距离
float navDistance = 0; //遍历计算距离
for (int i = 0; i < points.Length - 1; i++) {
navDistance+= Vector3.Distance (points , points [i + 1]);
} //导航距离在听觉距离范围内
if (navDistance < distanceOfView) {
return true;
} }
return false; }
8)向机器人守卫添加“EnemyAnimation。cs”脚本,该脚本实现机器人动画之间的切换,并且优化动作细节。
9)想机器人守卫添加“EnemyAI.cs”脚本组件,该组件控制机器人的具体行为,决定了机器人守卫什么时候攻击,什么时候追击,何时开枪射击等行为,
其判断依据是取决于与玩家之间的位置对象。10)向机器人守卫添加“EnemyShooting.cs”脚本组件,该脚本控制开枪时的效果,如打开闪光灯、打开激光,
并且对玩家造成伤害。
11)找到机器人的右手,在其下面拖拽一把手枪模型“prop_sciFiGun_low”。在手枪下创建一个空游戏对象,取名“Effects”。
12)在Effects对象上,添加Light组件,用于模拟开枪时的闪光灯。光源类型为point点光源,光强为2.5,Range=10。
13)在Effects对象上,添加LineRenderer组件,该组件模拟开枪时的激光,材质球选择“alpha_laserShot_fx”,起始和终止宽度(Width)设为0.1。
14)重复以上过程,创建另外两个机器人守卫。
Bug调试
(1)机器人的手枪即使在搭配是多次调试,但在运行时,当机器人守卫攻击入侵者时,手枪还是位置偏离严重。影响游戏观感。
解决方法:在游戏调试运行过程中,在机器人守卫攻击入侵者那一帧时暂停,将手枪位置调好,将它的transform值copy component,
退出运行,将手枪的transform值Paste componentValues,之后运行即可。
(2)发现在运行时当逃离至电梯里,上升时,可以跳出,跳进电梯。
解决方法:这是由于创建电梯时第七步没有做好,首先,应该让外面的大红门不可见,然后添加BoxCollider碰撞器,
原理,人物是刚体,由于重力必须向下落,所以必须有碰撞器拖着它,墙壁也需要加碰撞器,需要注意的是,在安装电梯栅栏门的碰撞器是,
需要展开,给两个门分别安装一个。
这里我给大家提供了完整所有的资源包,并非打包好的exe,但可以直接使用。在unity打开自取,兄弟们读贴十分钟,写贴两小时,希望不要吝啬。
所有资源.txt
(87 Bytes, 下载次数: 107)
或者百度网盘,谢谢支持,资源附上
|
-
免费评分
-
查看全部评分
|