运用到开发环境配置、编辑器基本知识、物理刚体、预制体、碰撞检测、动画状态机、C#脚本生命周期、Canvas界面知识、人物控制、摄像机跟随、NavMesh-AI导航组件等基本知识
制作流程
1.安装并配置,熟悉编辑器工具
Unity3D是由Unity Technologies开发的一个能让玩家轻松创建诸如三维游戏、虚拟现实、实时电 影与动画、建筑可视化、数字教育、汽车/运输与制造等众多类型互动内容的多平台的综合型游戏开 发工具,是一款功能强大的专业游戏引擎。Unity类似于Director,Blender,Virtools或Torque Game Builder等利用交互的图形化开发环境为首要方式的软件。
本次用的专题讨论用的是unity2022.
2.导入资源文件
可以去Window->Asset Store下载想要的场景,在搜索栏搜Tutorial Resources 。
这里下载的Tutorial Resources,添加到我的资源并在unity中打开拖入人物,通过GameObject->Align with view调整视角
3.动画化人物游戏角色
创建一个动画器控制器,直接在资源里面右键(或导航栏资源上单机)里的创建一个动画器控制器即可,命名后点击就会打开Animator面板,就可以对于动画进行配置等操作:
4.完善游戏人物的设置
添加刚体组件和碰撞体组件,刚体组件是让物体产生物理行为的组件,而碰撞体组件则是让刚体与物体产生碰撞的组件
刚体(Rigidbody)组件参数
在 Unity 中,若想要一个物体具有在现实世界中的物理效果,比如受重力影响,就要为其添加 Rigidbody 组件,该组件是让物体产生物理行为的组件。通过刚体组件可以给物体添加一些常见的物理属性,如质量、摩擦力、碰撞参数等。
在物理学中,刚体是一个理想模型,通常把在外力作用下,物体的形状和大小保持不变,而且内部各部分相对位置保持恒定的理想模型称为刚体。
按下物体对象的 Inspector 面板的 Add Component 按钮,搜索 Rigidbody 即可添加该组件。(或通过 Physics->Rigidbody 分类)
碰撞体(Collider)组件参数
碰撞体组件定义了物体的物理形状,且碰撞体本身是隐形的,大家可以想想空气墙的例子。
当你创建了一个 Cube,该物体就自带了一个 Box Collider。最简单且最节省计算资源的碰撞体就是一系列基本碰撞体。当你右键创建一系列基本模型时,它们就自带了一系列基本碰撞体。
一个物体可以带有多个碰撞体组件,这样就形成了组合碰撞体。
5.游戏环境的基础设置
注意这里因为我是用的2022版的,NavMesh-AI导
航组件需要手动下载。
在菜单栏中选中Window->Navigation打开Navigation窗口,Bake窗口主要是定义地形对寻路的影响。
6.游戏人物的控制
通过写脚本(unity以c#为脚本语言)实现,transform.Translate(方向*速度*帧率)实现角色位移,乘上帧率是为了避免帧率对速度的影响。
通过在脚本上定义变量,用public将其暴露出来给unity,结合“ 动画控制器” 用于状态判断。
(如人物速度speed暴露给控制器后,控制器用其作为判断条件,通过不断的判断,在不同的状态间快速跳转,实现动画播放与人物位移同步)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 玩家控制的脚本
/// </summary>
public class PlayMovement : MonoBehaviour
{
//世界坐标下的目标方向向量
private Vector3 m_Movement;
//旋转的四元数
private Quaternion m_Rotation=Quaternion.identity;
//游戏的对象的动画组件、刚体组件
private Animator anim;
private Rigidbody rd;
//游戏对象的每一秒的旋转速度
private float m_Speed = 20f;
//音频组件--控制脚步声的音频
AudioSource audioSource;
// Start is called before the first frame update
void Start()
{
rd=GetComponent<Rigidbody>();
anim=GetComponent<Animator>();
audioSource=rd.GetComponent<AudioSource>();
}
// Update is called once per frame
void FixedUpdate()
{
//辅助记录目标坐标的水平分量与垂直分量。
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
//根据键盘的键值输入决定是否进行行走动画的播放
bool IsHori = !Mathf.Approximately(horizontal, 0f);
bool IsVori = !Mathf.Approximately(vertical, 0f);
bool iswalking = IsHori || IsVori;
anim.SetBool("IsWalking", iswalking);
//控制脚步声声音的变化
if (iswalking)
{
//人物正在移动,播放脚步声音
if (!audioSource.isPlaying)
{
audioSource.Play();
}
}
else
{
//没有移动,关闭脚步声的播放
audioSource.Stop();
}
//将键盘获取到的键值输入赋值给目标坐标
m_Movement.Set(horizontal,0f,vertical);
//归一(单位)化,得到世界坐标下的目标方向向量
m_Movement.Normalize();
//获取每帧应到达的世界坐标下的前向方向向量
//用于计算旋转后角度的四元数
Vector3 desiredForward = Vector3.RotateTowards(transform.forward,m_Movement,m_Speed*Time.deltaTime,0f);
//每帧旋转后的四元数(Transform组件视角下的角度)
m_Rotation=Quaternion.LookRotation(desiredForward);
}
//该方法在计算机、动画计算求值后,每一帧都会调用。
//解决根动画移动的问题,进行物理适时调用。
private void OnAnimatorMove()
{
//运用刚体组件控制物体的移动与旋转,下列两个方法传入的参数均为目标值
rd.MovePosition(transform.position + m_Movement * anim.deltaPosition.magnitude);
rd.MoveRotation(m_Rotation);
}
}
7.摄像机跟随游戏人物的控制
两种方法。这里我用写脚本实现,脚本如下:挂在摄像机上即可。
Vector3.Lerp(from, of, t):"from"和"of"以及API返回值都为向量,t为参数,用于返回差值向量 from+(to-from)*t
Transform.LookAt(Vector3):使游戏对象看向该坐标点(游戏对象的z轴指向Vector3)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
private Transform Player;
Vector3 offset;
// Start is called before the first frame update
void Start()
{
Player = GameObject.Find("JohnLemon").transform;
offset= transform.position-Player.position;
}
// Update is called once per frame
void Update()
{
transform.position = offset+Player.position;
}
}
8.设置游戏结束界面
添加背景图片
UI界面里,所有图片或者音乐使用的时候都需要转化为2D。将2D图片拖入并且设置为全屏即可。(按住ALT键选择图片模式)
这里我们要添加个脚本,,当人物触发某个条件,跳出游戏界面
public CanvasGroup FailBK;
bool IsExit=false;
bool IsFail=false;
public float timer = 0f;
public AudioSource winaudio;
public AudioSource failaudio;
bool IsPlay;
// Start is called before the first frame update
private void OnTriggerEnter(Collider other)
{
if (other.gameObject == Player)
{
IsExit = true;
}
}
public void Caught()
{
IsFail = true;
}
void Start()
{
}
// Update is called once per frame
void Update()
{
if (IsExit)
{
EndLever(EixtBK,false,winaudio);
}
else if (IsFail)
{
EndLever(FailBK,true,failaudio);
}
}
void EndLever(CanvasGroup igCanvasGroup,bool doRestart,AudioSource playaudio)
{
if (!IsPlay)
{
playaudio.Play();
IsPlay= true;
}
timer += Time.deltaTime;
igCanvasGroup.alpha = timer / fadeDuration;
if (timer > fadeDuration + displayDuration)
{
if (doRestart)
{
SceneManager.LoadScene("SampleScene");
}
else if (!doRestart)
{
Application.Quit();
}
}
}
}
9.游戏的发布
游戏场景做好后,Ctrl+S保存场景并命名。把场景放在自己创建的Scene文件夹下。点击菜单 File-Bulid Settings 会出现多个发布平台,一般发布在PC平台,当然如果你要想发布在其它平台也是可以的,但是需要相应环境配置和搭建过程 。点击ADD Open Scenes 添加要发布的场景,这里我们只做了一个场景,如果有多个场景的话也可以一起发布,不过要注意发布的顺序,在之后分享场景的切换时再详细讲解。最后单击Build把游戏发布到你的电脑上。发布之后你就可以点击后缀为exe的程序运行你的游戏啦!(运行时要注意把Windowed打上勾,意窗口化运行你的游戏,因为我们没给游戏添加退出方法,如果不勾选的话,你就只能任务管理器强制退出啦。。)
总结
在学习Unity之前,我首先需要了解一些计算机基础知识,如C#编程语言、数据结构和算法等。这些知识是学习Unity的基础,只有掌握了这些知识,才能更好地学习Unity。在学习过程中,我通过阅读教材、观看视频教程、参加线上课程等方式,逐步掌握了这些基础知识。
在掌握了基础知识之后,我开始学习Unity的基本操作。首先,我通过阅读官方文档和教程,了解了Unity的界面布局、场景管理、资源导入等方面的知识。接着,我通过实际操作,学会了如何创建项目、添加组件、编写脚本等基本操作。在这个过程中,我逐渐熟悉了Unity的操作界面,为后续的学习打下了基础。
回顾自己学习Unity的过程,我深感收获颇丰。在这个过程中,我不仅掌握了Unity的各种功能和技巧,还积累了丰富的项目经验。同时,我还学会了如何与他人合作,共同完成一个游戏项目。在今后的学习和工作中,我将继续努力,不断提高自己,为游戏开发事业贡献自己的一份力量。最后,我要感谢那些在我学习过程中给予我帮助和支持的人,是你们让我更加坚定地走在游戏开发的道路上。