文章目录
- 前言
- 游戏要求
- 游戏分析
- 游戏实现
- 总结
- 选做题:打靶游戏
前言
中山大学数据科学与计算机学院3D游戏课程学习记录博客。
游戏代码: gitee 游戏视频: bilibili 参考师兄的博客: 师兄博客
游戏要求
- 按 adapter模式设计图修改飞碟游戏。
- 使它同时支持物理运动与运动学(变换)运动。
游戏分析
重用游戏五的代码,需要增加物理运动的相关代码,即PhysisDiskFlyAction.cs;
然后在FirstController.cs中根据情况选择调用物理运动和运动学运动两种运动方式,就可以实现adapter模式。
adapter模式:
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
游戏实现
- PhysisDiskFlyAction.cs的实现:
PhysisDiskFlyAction.cs的实现模仿DiskFlyAction.cs,继承自SSAction;
因为要使用物理引擎,所以通过FixedUpdate来实现位置更新;
在Start()函数中给飞碟施加一个冲击力。
public class PhysisDiskFlyAction : SSAction
{
private Vector3 start_vector;
public float power;
private PhysisDiskFlyAction() { }
public static PhysisDiskFlyAction GetSSAction(int lor, float power) {
PhysisDiskFlyAction action = CreateInstance<PhysisDiskFlyAction>();
if (lor == -1) {
action.start_vector = Vector3.left * power;
}
else {
action.start_vector = Vector3.right * power;
}
action.power = power;
return action;
}
public override void Update() { }
//物理引擎更新
public override void FixedUpdate() {
if (transform.position.y <= -10f) {
gameobject.GetComponent<Rigidbody>().velocity = new Vector3(0, 0, 0);
this.destroy = true;
this.callback.SSActionEvent(this);
}
}
public override void Start() {
gameobject.GetComponent<Rigidbody>().AddForce(start_vector*3, ForceMode.Impulse);
}
}
- SSAction.cs和SSActionManager.cs的改进:
SSAction.cs应该添加FixedUpdate函数,以便PhysisDiskFlyAction从SSAction中继承;
SSActionManager.cs在调用Update的时候也应该调用FixedUpdate,以便物理运动更新。
public class SSAction : ScriptableObject {
//物理引擎配置
public virtual void FixedUpdate() {
throw new System.NotImplementedException();
}
}
public class SSActionManager : MonoBehaviour, ISSActionCallback {
protected void Update() {
foreach (KeyValuePair<int, SSAction> kv in actions) {
SSAction ac = kv.Value;
if (ac.destroy) {
waitingDelete.Add(ac.GetInstanceID());
}
else if (ac.enable) {
ac.Update();
ac.FixedUpdate();//添加物理运动
}
}
}
- FlyActionManager.cs的改进:
对应物理学运动,增加一个physicsDiskFly函数,来使用物理引擎。
public class FlyActionManager : SSActionManager {
public void DiskFly(GameObject disk, float angle, float power) {
//运动学运动
}
public void physicsDiskFly(GameObject disk,float power){
//物理引擎运动
}
}
- UserGUI.cs的改进:
UserGUI.cs应该支持一个改变模式按钮来改变模式;
模式使用mode表示,通过mode^1来改变模式;
0代表运动学运动,1代表物理学运动。
public class UserGUI : MonoBehaviour {
private int mode=0;
void OnGUI () {
if (game_start) {
//游戏运行操作
}
else {
//游戏未开始操作
//如果想全程支持切换功能,可以把“改变模式”的生成代码放到if(game_start)外面
if(GUI.Button(new Rect(Screen.width / 2 - 30, Screen.height / 2 - 180, 80, 20), "改变模式")){
mode=mode^1;
}
}
}
public int getMode(){
return mode;
}
}
- FirstController.cs的改进:
FirstController.cs从UserGUI.cs中得到mode值,并且调用对应的函数。
public class FirstController : MonoBehaviour, ISceneController, IUserAction {
private void SendDisk(int type) {
if(user_gui.getMode()==1){
action_manager.physicsDiskFly(disk,power);
}else{
action_manager.DiskFly(disk, angle, power);
}
}
}
- 给预制增加刚体组件:
物理引擎需要预制具有刚体组件。
通过AddComponent->Rigidbody来增加。
至此,游戏设计完成。
总结
本次实验主要了解了物理引擎的使用,使用物理引擎就不用进行复杂的公式计算,还是比较方便的。
选做题:打靶游戏
博客链接:打靶游戏