物理系统与碰撞
编写一个简单的鼠标打飞碟(Hit UFO)游戏
1. 改进飞碟(Hit UFO)游戏:
- 游戏内容要求:
- 按 adapter模式 设计图修改飞碟游戏
- 使它同时支持物理运动与运动学(变换)运动
由于加入了运动学和物理运动,所以要用适配器模式让新的动作适配我们的代码,引入新的适配器类IActionManager,新的类图如图:
适配器接口类的代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public interface IActionManager {
void Play();
void Pause();
}
新的运动学代码如下:
PhysicsEmitAction类:
public class PhysicsEmitAction : SSAction {
public Vector3 speed;
public static PhysicsEmitAction GetSSAction()
{
PhysicsEmitAction action = CreateInstance<PhysicsEmitAction>();
return action;
}
public override void Start()
{
}
public override void Update()
{
if (transform.position.y < -10 || transform.position.x <= -20 || transform.position.x >= 20)
{
gameObject.GetComponent<Rigidbody>().isKinematic = true;
gameObject.GetComponent<Rigidbody>().velocity = new Vector3(0,0,-10);
transform.position = Vector3.down;
callback.SSActionEvent(this);
}
}
}
PhysicsActionManager类:
public class PhysicsActionManager : SSActionManager, ISSActionCallback, IActionManager {
public FirstSceneController sceneController;
public List<PhysicsEmitAction> seq = new List<PhysicsEmitAction>();
public UserClickAction userClickAction;
public UFOFactory factory;
protected void Start()
{
sceneController = (FirstSceneController)SSDirector.getInstance().current;
sceneController.actionManager = this;
factory = Singleton<UFOFactory>.Instance;
}
public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Completed, int intParam = 0, string strParam = null, Object objParam = null)
{
factory.Recycleufo(source.gameObject);
seq.Remove(source as PhysicsEmitAction);
source.destory = true;
if (FirstSceneController.times >= 30)
sceneController.flag = 1;
}
public void CheckEvent(SSAction source, SSActionEventType events = SSActionEventType.Completed, int intParam = 0, string strParam = null, Object objParam = null)
{
}
public void Pause()
{
if (sceneController.flag == 0)
{
foreach (var k in seq)
{
k.speed = k.transform.GetComponent<Rigidbody>().velocity;
k.transform.GetComponent<Rigidbody>().isKinematic = true;
}
sceneController.flag = 2;
}
else if (sceneController.flag == 2)
{
foreach (var k in seq)
{
k.transform.GetComponent<Rigidbody>().isKinematic = false;
k.transform.GetComponent<Rigidbody>().velocity = k.speed;
}
sceneController.flag = 0;
}
}
public void Play()
{
if (factory.used_ufos.Count > 0)
{
GameObject disk = factory.used_ufos[0];
float x = Random.Range(-5, 5);
disk.GetComponent<Rigidbody>().isKinematic = false;
disk.GetComponent<Rigidbody>().velocity = new Vector3(x, 8 * (Mathf.CeilToInt(FirstSceneController.times / 10) + 1), 6);
disk.GetComponent<Rigidbody>().AddForce(new Vector3(0,8.8f, 0),ForceMode.Force);
PhysicsEmitAction physicsEmitAction = PhysicsEmitAction.GetSSAction();
seq.Add(physicsEmitAction);
this.RunAction(disk, physicsEmitAction, this);
factory.used_ufos.RemoveAt(0);
}
if (Input.GetMouseButtonDown(0) && sceneController.flag == 0)
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitGameObject;
if (Physics.Raycast(ray, out hitGameObject))
{
GameObject gameObject = hitGameObject.collider.gameObject;
Debug.Log(gameObject.tag);
if (gameObject.tag == "ufo")
{
gameObject.transform.position=new Vector3(0,1,-10);
if(gameObject.transform.GetComponent<Renderer>().material.color==Color.red)
userClickAction = UserClickAction.GetSSAction(3);
else if(gameObject.transform.GetComponent<Renderer>().material.color==Color.green)
userClickAction = UserClickAction.GetSSAction(2);
else if(gameObject.transform.GetComponent<Renderer>().material.color==Color.blue)
userClickAction = UserClickAction.GetSSAction(1);
this.RunAction(gameObject, userClickAction, this);
}
}
}
base.Update();
}
}
需要修改的地方:
UFOFactory:
public void Recycleufo(GameObject usedUFO)
{
usedUFO.transform.position = new Vector3 (0, -1, -10);
//########################
usedUFO.gameObject.GetComponent<Rigidbody> ().isKinematic = true; //让UFO停止掉落
free_ufos.Add(usedUFO);
}
//#################################
ufo.gameObject.GetComponent<Rigidbody> ().isKinematic = false; //恢复UFO掉落属性
float x = Random.Range(-10.0f, 10.0f);
ufo.transform.position = new Vector3(x, 0, 0);
ufo.transform.Rotate(new Vector3(x < 0? -x*9 : x*9, 0, 0));