-
基本操作演练
1.1 下载Fantasy Skybox FREE, 构建自己的游戏场景。
首先先进入Asset Store中搜索Fantasy Skybox FREE,下载到unity中:
下载完成后在unity内打开Fantasy Skybox的文件夹,在其中找到Sample terrain直接导入到Scene中。这一步自己利用包内的资源也可以做,但说实话做的挺丑的,所以还不如直接用它的Sample,再用笔刷刷一点花花草草的细节,最后的效果如下:
进一步增添细节,选择Skybox中的任一个预设拖到Camera上 ,改变背景天空的模样,同时加入一个第三人称玩家,通过控制他来对刚刚创建的地形进行探索,效果图如下:
1.2 总结
游戏对象包括3D游戏对象、2D游戏对象、事件、灯光、声音、视频、UI界面、摄像机等。其中目前最常用的为3D游戏对象,灯光和摄像机,UI界面。
3D游戏对象的用法多为创建一个特定形状的对象,将其作为预设加入场景中。
摄像机对象的用法多为设定一个便于玩家观看的角度或是设定为其他游戏对象的子对象(便于跟踪模型移动)
灯光的用法多为根据需要创建灯光对象,给人物模型或者场景打光。
UI界面的用法多为创建一个特定形状的对象,将其作为预设加入场景中。
声音界面的用法多为创建声音对象(如FPS中的枪声以及NPC走路的声音),将其作为预设加入场景中。
编程实践题
此处我选择的是第二项任务,即还原小说《大主宰》中的一段片段,该片段中主要描写了主角在空中飞行穿梭的过程,基于这一场景,我的游戏设计为比较简单的“青蛙过河”式的游戏设计,即从起始点通过跳跃到达另一侧。
为了实现上述的基本构想,我设置了如下几种游戏对象:
- Cube游戏对象:利用unity自带的3D Object,生成多个Cube对象,调整Scale中的值,制成起始、结束平台以及跳跃平台,存进预设中。
- Terrain游戏对象:这个游戏对象的作用在于还原原片段,即当主角到达结束平台时,会有一个NPC帮助他前往大陆,而Terrain游戏对象就代表了这个大陆。
- AIThirdPersonController:这一游戏对象是Unity官方发布的Standard Asset包内的预设,在这里是代表了上述的NPC
- FPSController:这一游戏对象也是Unity官方发布的Standard Asset包内的预设,作为主角,可供玩家进行第一人称操作。
设置完成了这些游戏对象,构建了游戏世界后,其次就是游戏的基本玩法:玩家从起始平台复活,对岸会开始生成三排“陨石”移动过来,同时为了让游戏更加有挑战性,我将陨石块的大小设为了在一定范围内随机生成的整数,不仅如此,我还设置让对岸平台来回移动,更具挑战性。玩家可以通过组合按wasd键走路,空格键跳跃,左shift加速,跳跃到对岸NPC处。到达NPC附近时,会有3秒的倒计时,目的是为了检验是否真的稳定跳到平台上了以及加入NPC互动(碍于技术力不足,没能实现)。倒计时结束后,玩家会被传送到新大陆上,此时即为游戏成功,玩家可以自由探索新大陆。
具体实现游戏对象动作管理的代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Model : MonoBehaviour
{
// Start is called before the first frame update
Queue<GameObject> s = new Queue<GameObject>();
GameObject endPlace;
//Vector3 endPos = new Vector3(10f,0f,0f);
bool flag = false;
public float speed = 1.0f;
private float timer = 0.0f;
private float waitTime = 2.0f;
private float scrollBar = 1.0f;
private int maxNum = 30;
void Start()
{
Time.timeScale = scrollBar;
GameObject startPlace = Instantiate(Resources.Load("Prefabs/StartPos") as GameObject);
startPlace.transform.position = new Vector3(30f,0f,-3f);
endPlace = Instantiate(Resources.Load("Prefabs/EndPos") as GameObject);
endPlace.transform.position = new Vector3(-5f,0.0f,0.0f);
GameObject target = Instantiate(Resources.Load("Prefabs/Target") as GameObject);
target.transform.position = new Vector3(-6f,0f,-1f);
target.transform.parent = endPlace.transform;
GameObject transport = Instantiate(Resources.Load("Prefabs/Target") as GameObject);
transport.transform.position = new Vector3(300f,1f,593f);
GameObject land = Instantiate(Resources.Load("Prefabs/Terrain") as GameObject);
land.transform.position = new Vector3(-200f,0f,106f);
GameObject cam = Instantiate(Resources.Load("Prefabs/Fps") as GameObject);
cam.transform.position = new Vector3(30f,1.54f,-3f);
}
// Update is called once per frame
void Update()
{
timer +=Time.deltaTime;
if (timer > waitTime){
createGameObj();
timer = timer - waitTime;
Time.timeScale = scrollBar;
}
GameObject[] temp = s.ToArray();
var step = speed * Time.deltaTime * 2.4f;
for (int i=0;i<s.Count;i++){
Vector3 endPos = new Vector3(60f,0f,temp[i].transform.position.z);
temp[i].transform.position = Vector3.MoveTowards(temp[i].transform.position,endPos,step);
}
Vector3 movePos = new Vector3(-5f,0f,16f);
Vector3 backPos = new Vector3(-5f,0f,0f);
if (!flag){
endPlace.transform.position = Vector3.MoveTowards(endPlace.transform.position,movePos,step);
if (endPlace.transform.position == movePos) flag = true;
}
else{
endPlace.transform.position = Vector3.MoveTowards(endPlace.transform.position,backPos,step);
if (endPlace.transform.position == backPos) flag = false;
}
if (s.Count > maxNum){
for (int i=0;i<3;i++){
GameObject tmp = s.Dequeue();
Destroy(tmp);
}
}
}
void createGameObj(){
for (int i=0;i < 3;i++){
GameObject tmp = Instantiate(Resources.Load("Prefabs/Cube") as GameObject);
float scale = Random.Range(2,4);
tmp.transform.position = new Vector3(0,0,1 + 5f * i);
tmp.transform.localScale = new Vector3(scale,0.3f,scale);
s.Enqueue(tmp);
}
}
}
本段代码实现了游戏对象的加载,动态生成“陨石”以及控制陨石的数量不超过一定值(此处maxNum为30),同时也实现了对岸平台的移动。
人物移动的代码大部分是Unity已经帮我写好了的,我只是加了一些简单的验证,列如下:
RigidbodyFirstPersonController.cs
private float timer = 0.0f;
private float waitTime = 3.0f;
private float scrollBar = 1.0f;
private void Update()
{
RotateView();
if (CrossPlatformInputManager.GetButtonDown("Jump") && !m_Jump)
{
m_Jump = true;
}
check();
}
private void check(){
if (transform.position.y <= -10){
transform.position = new Vector3(30f,0.74f,-1.71f);
}
if (transform.position.x < -3 && transform.position.y > 0.5){
timer += Time.deltaTime;
if (timer > waitTime){
transform.position = new Vector3(303f,1f,593f);
}
}
主要就是判断人物掉落并复位,以及最后的3秒验证传送时间,同时我为了让冲刺更快,也自己稍微更改了一下冲刺的速度,从原来的2.0f更改为了4.0f。
演示视频
Assignment 4 大主宰小游戏_哔哩哔哩_bilibili
这里有点不一样的地方在于,我当时录这个视频的时候忘了把Fps改成预设了,后来改正了(可从前文代码看出),不过不影响游戏的实际游玩效果。