这几天参加了一个比赛,利用unity做了一个小游戏,这里记录一下自己做游戏的过程,同时整理一下这段时间的收获,算是这次比赛的一个总结。
因为我的unity都是自学的,平时用的也比较少,所以掌握的都是一些最基本的操作,如果有错误或是更好的解决方案也希望大家可以提出来,共同学习。
以下将会描述一个简单的游戏项目,由于项目比较简单,开发用时也比较少,适合新手和小白观看,如果需要交流可以留言。
开发环境unity2018.2.1f
编程环境vs2019
游戏中涉及到的地形和任务模型都是从网上下载的免费的资源,所以可以节省我们大量的时间,游戏的开发过程主要分为三部分:第一部分是场景搭建 利用从网上搜集的资源,搭建自己的游戏环境,在这里不做赘述(其中游戏中的大量UI是我的队友设计的这里也不在描述)。
第二部分游戏逻辑和剧情设定 此项目中描述的游戏逻辑较为简单,就是在四个不同的场景完成任务,击杀任务目标,最后结束。剧情设定可以根据自己的喜好进行编辑,本项目描述了主角通过四族历练的过程,是游戏的第一部分。
第三部分游戏和逻辑实现 这是我想要描述的重点,包括制作游戏开始菜单,场景跳转,dialogSystem实现的人物对话,简单的相机跟随和easytouch5的简单使用。(dialogsystem是一个用来做对话的插件,使用它可以很轻松的制作对话。easytouch是unity的触控插件,可以用它来很轻松的实现触摸,滑动,拖拽,多指操作等)
下面是游戏菜单截图
基本实现方法是先建立一个新的sence,可以命名为menu,可以利用这个名称来加载场景。之后建立一个canvas,在上面划分选区,我的方法是划分了三个选区,第一个选区命名为mainmenu,用来放开始游戏 退出游戏和游戏名称,第二个选区是设置选区,可以用来调节参数的大小,第三个则是 帮助选区,用来描述游戏背景和游戏帮助。
先说一下为什么要划分选区,因为当我们按设置的时候,我们可以通过隐藏mainmenu,将option面板的内容显示出来,之后在option界面设计一个返回按钮,当按钮按下时 ,再将mainmenu显示出来,同理我们也可以这样实现帮助页面。这里实现机制有两种,一种是通过setactive设置可见不可见另外一种是将页面移动到视野外,从网上查的资料来看,setactive这种方法会引起大量的gc,不推荐大量使用。
unity提供的button,可以很方便的执行我们设定的方法。
我们可以统一设定一个menucontrol,来当做我们脚本的承载对象,然后在上面挂载我们的脚本,这样就只需要将我们的承载对象拖到对象上,选择特定的方法就可以了。
然后我们说一下加载界面和进度条的实现,进度条使用synchronize来实现,动态改变slider的value
下面附上menucontroller.cs的内容
public class menucontroller : MonoBehaviour {
public GameObject loading;
public GameObject menu;
private AsyncOperation asyn=null;
public Slider slider;
public Text label;
// Use this for initialization
void Start() {
loading.SetActive(false);
}
void Update() {
if (asyn != null)
{
slider.value = asyn.progress;
label.text = "加载进度:" + (slider.value * 100) + "%";
}
//label.text = "加载进度0%";
}
public void StartGame() {
asyn = SceneManager.LoadSceneAsync("Scenes/main");//跳转的场景必须在setting中进行配置
menu.SetActive(false);
loading.SetActive(true);
}
public void exit() {
Application.Quit();
}
}
以上就是menu界面的主要内容
下面来讲一下主场景
这里面的主要包括摇杆,按钮,小地图,旋转像机
主要的难点是人物和怪物之间的交互。
摇杆使用的是easytouch5 中的joystick 使用简单控制就可以,支持相机跟随,相机跟随模式有两种,一种是follow一种是smooth follow具体的不同可以查看easytouch的说明文档,而且还支持相机的优化,具体内容请查看easytouch的说明文档或是其他相关资料。
关于相机的控制,这里我使用的是一种记录偏移量的方法,这种需要时刻跟player的坐标比较,得出偏移量,保证相机可以一直保持与player的关系。由于需要时刻计算,所以开销很大,关于优化的方法,希望有大佬可以不吝指教,供大家交流学习,必然不胜感激。下面是我控制相机的代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class cameracontroller : MonoBehaviour {
ETCJoystick view;
public GameObject player;
private Vector3 distance;
public Vector3 offset;
public Quaternion targer;
// Use this for initialization
void Start () {
view = ETCInput.GetControlJoystick("view");
targer = Quaternion.Euler(30, 0, 0);
}
// Update is called once per frame
void Update () {
distance =player.transform.position- this.transform.position;
if (distance != offset)
this.transform.Translate(distance+offset );
if (view.axisY.axisValue!=0)
this.transform.Rotate(new Vector3(-view.axisY.axisValue,0, 0));
if(view.axisX.axisValue != 0)
this.transform.Rotate(new Vector3(0, view.axisX.axisValue, 0));
if (view.axisX.axisValue == 0 && view.axisY.axisValue == 0)
{
this.transform.rotation = targer;
Debug.Log("旋转归位");
}
}
}
这里面同时包含了相机旋转和归位的代码。
之后是使用dialogSystem构建对话系统,可以参考相应的文章,比较简单,这里不进行赘述。
最后是怪物和player的交互,我只提供一种思路,就是设置一个变量,用来保存player的slider的value和monster中的slider value
然后根据特定的条件,比如动作执行完毕或是产生碰撞,扣除指定的血量,但是这些方法都存在写bug,希望有大佬可以提出新的解决方法,交流学习。