物理系统与碰撞
1、改进飞碟(Hit UFO)游戏:
游戏内容要求:
1.按 adapter模式 设计图修改飞碟游戏
2.使它同时支持物理运动与运动学(变换)运动
新的设计:
可以看出,本次的目的在于不放弃 CCActionManager的条件下,引入PhysisActionManager,说白了就是加个开关来调节模式,为此引入IActionManager。上次作业中round的控制是在FirstController里完成的,理论上这次应该拿出来再给一个新的类,但是看了下貌似只需要加一个函数就完事了。虽然分出去代码结构更清晰
首先是对CCActionManager的改动,需要加入IActionManager的接口。
CCFlyAction中也要将飞碟的初始属性修改运动学运动。
之后是物理运动实现部分。
PhysisActionManager:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PhysisActionManager :SSActionManager, ISSActionCallback, IActionManager
{
// Start is called before the first frame update
public PhysisFlyAction flyAction;
public FirstController controller;
protected new void Start()
{
controller=SSDirector.getInstance().currentSceneController as FirstController;
}
public void Fly(GameObject obj, float speed, Vector3 direction){
flyAction=PhysisFlyAction.GetSSAction(direction,speed);
this.RunAction(obj,flyAction,this);
}
public void SSActionEvent(SSAction source,
SSActionEventType events=SSActionEventType.Competed,
int intParam=0,
string strParam=null,
Object objectParam=null){
controller.ufoFactory.FreeUFO(source.gameObject);
}
}
PhysisFlyAction:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PhysisFlyAction : SSAction
{
float speed; //水平速度
Vector3 direction; //飞行方向
public static PhysisFlyAction GetSSAction(Vector3 direction, float speed)
{
PhysisFlyAction action = ScriptableObject.CreateInstance<PhysisFlyAction>();
action.speed = speed;
action.direction = direction;
return action;
}
public override void Start()
{
gameObject.GetComponent<Rigidbody>().isKinematic = false;
//为物体增加水平初速度
gameObject.GetComponent<Rigidbody>().velocity = speed * direction;
}
public override void Update()
{
if (this.transform.position.y < -8)
{
this.destroy = true;
this.enable = false;
this.callback.SSActionEvent(this);
}
}
}
FirstController中需要加入模式切换的函数,具体修改如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FirstController : MonoBehaviour, ISceneController, IUserAction {
private bool isRuning;
public UFOFactory ufoFactory;
private int[] roundUFOs;
private int score;
private int round;
private float sendTime;
private bool model;
int sendCnt;
private IActionManager actionManager;
// the first scripts
void Awake () {
SSDirector director = SSDirector.getInstance ();
director.currentSceneController = this;
director.currentSceneController.LoadResources ();
this.gameObject.AddComponent<UserGUI>();
this.gameObject.AddComponent<CCActionManager>();
this.gameObject.AddComponent<PhysisActionManager>();
ufoFactory=UFOFactory.getInstance();
roundUFOs=new int[]{3,5,9,11,15};
score=round=sendCnt=0;
sendTime=0;
sendCnt =0;
model = true;
actionManager=this.gameObject.GetComponent<CCActionManager>();
}
// loading resources for the first scence
public void LoadResources () {
isRuning=true;
}
public void SendUFO(){
GameObject ufo=ufoFactory.GetUFO(round);
ufo.transform.position=new Vector3(-ufo.GetComponent<UFOData>().direction.x * 7, UnityEngine.Random.Range(0f, 8f), 0);
ufo.SetActive(true);
actionManager.Fly(ufo,ufo.GetComponent<UFOData>().speed,ufo.GetComponent<UFOData>().direction);
}
public bool GetIsRuning(){
return isRuning;
}
public void JudgeCallback(bool isRuning,int score){
this.score+=score;
this.gameObject.GetComponent<UserGUI>().score=this.score;
this.isRuning=isRuning;
}
public void ChangeMode(){
model=!model;
if(model){
actionManager=this.gameObject.GetComponent<CCActionManager>();
}
else{
actionManager=this.gameObject.GetComponent<PhysisActionManager>();
}
}
public void Pause ()
{
throw new System.NotImplementedException ();
}
public void Resume ()
{
throw new System.NotImplementedException ();
}
#region IUserAction implementation
public void Restart ()
{
isRuning=true;
this.gameObject.GetComponent<UserGUI>().gameMessage="";
this.gameObject.GetComponent<UserGUI>().score=0;
score=round=sendCnt=0;
sendTime=0;
ufoFactory.FreeALL();
}
#endregion
void Start () {
}
void Update () {
sendTime+=Time.deltaTime;
if(sendTime>2){
sendTime=0;
for(int i = 0; i < 5 && sendCnt < roundUFOs[round]; i++){
sendCnt++;
SendUFO();
}
if(sendCnt == roundUFOs[round]&&round==roundUFOs.Length-1){
isRuning=false;
gameObject.GetComponent<UserGUI>().gameMessage = "Time Out!";
}
if(sendCnt == roundUFOs[round] && round < roundUFOs.Length - 1){
sendCnt = 0;
round++;
}
}
}
}
最后在UserGUI中在加入一个按钮就好
值得一提的是,要在预制体飞碟上加上刚体属性,由于选择了默认使用重力,在运动轨迹控制那里只需要加上水平速度即可。并且加上了刚体属性后,模型之间会产生碰撞,使得运动看起来更真实了一些。