Unity3D学习(7)之物理引擎的应用与代码复用
Unity3D的物理引擎做得很不错,让物体的运动更加贴近现实了。没有人喜欢高深的数学,去计算复杂的运动曲线和力学。使用物理引擎,而你仅需要高中的物理(牛顿!三定律, F = m * a)。
- 物理引擎是一种软件组件,用于仿真物理世界运动。 这种仿真包括刚体力学、流体力学以及碰撞检测。
- 物理引擎通过为刚性物体赋予真实的物理属性,在外部力的作用下,计算运动、旋转和碰撞。
public interface ISceneController//导演场记通信接口
{void LoadResources();//void Pause ();//void Resume ();
}public class SSDirector : System.Object
{private static SSDirector _instance;public ISceneController currentScenceController { get; set; }public bool running { get; set; }public static SSDirector getInstance(){if (_instance == null){_instance = new SSDirector();}return _instance;}public int getFPS(){return Application.targetFrameRate;}public void setFPS(int fps){Application.targetFrameRate = fps;}
}
SceneController.cs
public class SceneController : MonoBehaviour, ISceneController, IUserAction
{public IActionManager actionManager { get; set; }//动作管理器public DiskFactory factory { get; set; }//游戏工厂public Recorder scoreRecorder { get; set; }//游戏记分员public int round = 0;//轮数public Text RoundText;//轮数文本public Text GameText;//倒计时文本public Text FinalText;//结束文本public int game = 0;//记录游戏进行情况public int num = 0;//每轮的飞碟数量GameObject explosion;//爆炸效果public int CoolTimes = 3; //准备时间// Use this for initializationvoid Awake()//创建导演实例并载入资源{SSDirector director = SSDirector.getInstance();director.setFPS(60);director.currentScenceController = this;director.currentScenceController.LoadResources();}void Start(){round = 1;//开始游戏设置为第一轮}// Update is called once per framevoid Update(){RoundText.text = "Round:" + round.ToString();//将轮数信息打印出来if(game == 2){GameOver();//判断游戏结束}}public IEnumerator waitForOneSecond() //协程技术实现倒计时3秒{while (CoolTimes >= 0 && game == 3){GameText.text = CoolTimes.ToString(); //将倒计时剩余时间打印在屏幕上print("还剩" + CoolTimes);yield return new WaitForSeconds(1);//等待一秒CoolTimes--;}GameText.text = "";game = 1; //标记游戏开始}public void GameOver(){FinalText.text = "Game Over!!!";//游戏结束显示}public void StartGame() //实现IUserAction接口开始游戏{num = 0;if (game == 0){game = 3; //进入倒计时模式StartCoroutine(waitForOneSecond()); //启动协程}}public void ReStart() //实现IUserAction接口重启游戏{SceneManager.LoadScene("task1");game = 0;}public void ShowDetail() //实现IUserAction接口显示游戏介绍{GUI.Label(new Rect(220, 50, 350, 250), "Use your mouse click disk, you will get 1 point for green Disk,2 for yellow Disk,3 for red Disk,you should get 20 points to pass round1,40 to pass round2,60 to pass round3.There are three round.Good Luck!!!");}public void hit() //实现IUserAction接口判断击中事件{if (game == 1){Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);RaycastHit hit;if (Physics.Raycast(ray, out hit)){if (hit.transform.tag == "Disk"){explosion.transform.position = hit.collider.gameObject.transform.position;explosion.GetComponent<Renderer>().material = hit.collider.gameObject.GetComponent<Renderer>().material;explosion.GetComponent<ParticleSystem>().Play();hit.collider.gameObject.SetActive(false);print("Hit!!!");hit.collider.gameObject.GetComponent<DiskData2>().hit = true;scoreRecorder.add();}}}}public void LoadResources() //载入资源{explosion = Instantiate(Resources.Load("prefabs/Explosion"), new Vector3(-40, 0, 0), Quaternion.identity) as GameObject;Instantiate(Resources.Load("prefabs/Light"));}
}
UserGUI.cs
public interface IUserAction
{void StartGame();void ShowDetail();void ReStart();void hit();
}public class UserGUI : MonoBehaviour
{private IUserAction action;// Use this for initializationvoid Start(){action = SSDirector.getInstance().currentScenceController as IUserAction;}void OnGUI(){GUIStyle fontstyle1 = new GUIStyle();fontstyle1.fontSize = 50;fontstyle1.normal.textColor = new Color(255, 255, 255);if (GUI.RepeatButton(new Rect(0, 0, 120, 40), "Shooting Disk")){action.ShowDetail();}if (GUI.Button(new Rect(0, 60, 120, 40), "STARTGAME")){action.StartGame();}if (GUI.Button(new Rect(0, 120, 120, 40), "RESTART")){action.ReStart();}if (Input.GetMouseButtonDown(0)){action.hit();}}// Update is called once per framevoid Update(){//}
}
Factory.cs
public class DiskFactory : MonoBehaviour
{private static DiskFactory _instance;public SceneController sceneControler { get; set; }//场记public Recorder scoreRecorder;//计分员GameObject diskPrefab;//飞碟模板DiskData2 diskData;//飞碟数据public List<GameObject> used;public List<GameObject> free;// Use this for initializationprivate void Awake(){if (_instance == null){_instance = Singleton<DiskFactory>.Instance;//单实例化_instance.used = new List<GameObject>();_instance.free = new List<GameObject>();diskPrefab = Instantiate(Resources.Load<GameObject>("Prefabs/disk"), new Vector3(40,0,0), Quaternion.identity);}}public void Start(){sceneControler = (SceneController)SSDirector.getInstance().currentScenceController; //引入场记sceneControler.factory = this;//设置场记的工厂scoreRecorder = sceneControler.scoreRecorder;//引入记分员}public GameObject getDisk(int round) //取得飞碟{if (sceneControler.num == 31 && scoreRecorder.Score >= round * 20) //每轮31个飞碟,看分数是否达标决定进入下一轮或者结束游戏{sceneControler.round++;sceneControler.num = 0;} else if(sceneControler.num == 31 && scoreRecorder.Score < round * 20){sceneControler.game = 2;//游戏结束}GameObject newDisk;if (free.Count == 0){newDisk = GameObject.Instantiate(diskPrefab) as GameObject;}else{newDisk = free[0];free.Remove(free[0]);}diskData = newDisk.GetComponent<DiskData2>(); //取出飞碟数据实现复用,提高效率switch (round) //根据轮数选择飞碟{case 1:diskData.size = 0.8f;diskData.color = Color.green;newDisk.transform.localScale = new Vector3(diskData.size, diskData.size, diskData.size);newDisk.GetComponent<Renderer>().material.color = diskData.color;break;case 2:diskData.size = 0.7f;diskData.color = Color.yellow;newDisk.transform.localScale = new Vector3(diskData.size, diskData.size, diskData.size);newDisk.GetComponent<Renderer>().material.color = diskData.color;break;case 3:diskData.size = 0.6f;diskData.color = Color.red;newDisk.transform.localScale = new Vector3(diskData.size, diskData.size, diskData.size);newDisk.GetComponent<Renderer>().material.color = diskData.color;break;}used.Add(newDisk);return newDisk;}public void freeDisk(GameObject disk1) //释放飞碟{for (int i = 0; i < used.Count; i++){if (used[i] == disk1){used.Remove(disk1);disk1.SetActive(true);free.Add(disk1);}}return;}
}
Sington.cs
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour{//场景单实例protected static T instance;public static T Instance{get{if(instance == null){instance = (T)FindObjectOfType(typeof(T));if(instance == null){Debug.LogError("An instance of " + typeof(T) + " is needed in the scene, but there is none.");}}return instance;}}
}
Recorder.cs
public class Recorder : MonoBehaviour {public Text ScoreText;//分数文本public float Score = 0;//分数public SceneController sceneControler { get; set; }//引入场记// Use this for initializationvoid Start () {sceneControler = (SceneController)SSDirector.getInstance().currentScenceController;sceneControler.scoreRecorder = this;//设置记分员}public void add() //加分{Score += sceneControler.round;}public void miss() //扣分{Score -= sceneControler.round;}// Update is called once per framevoid Update () {ScoreText.text = "Score:" + Score.ToString();//更新分数}
}
SSAction.cs
public enum SSActionEventType : int { Started, Competeted }public interface ISSActionCallback //动作管理器与动作通信接口
{void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,int intParam = 0, string strParam = null, Object objectParam = null);
}
//动作基类
public class SSAction : ScriptableObject
{public bool enable = true;public bool destroy = false;public GameObject gameobject { get; set; }public Transform transform { get; set; }public ISSActionCallback callback { get; set; }protected SSAction() { }public virtual void Start(){throw new System.NotImplementedException();}public virtual void Update(){throw new System.NotImplementedException();}public virtual void FixedUpdate(){//throw new System.NotImplementedException();}
}
SSActionManager.cs
public class SSActionManager : MonoBehaviour //动作管理器基类
{private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();private List<SSAction> waitingAdd = new List<SSAction>();private List<int> waitingDelete = new List<int>();// Use this for initializationvoid Start(){}// Update is called once per frameprotected void Update(){foreach (SSAction ac in waitingAdd) actions[ac.GetInstanceID()] = ac;waitingAdd.Clear();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();}}foreach (int key in waitingDelete){SSAction ac = actions[key]; actions.Remove(key); DestroyObject(ac);}waitingDelete.Clear();}public void RunAction(GameObject gameobject, SSAction action, ISSActionCallback manager){action.gameobject = gameobject;action.transform = gameobject.transform;action.callback = manager;waitingAdd.Add(action);action.Start();}
}
DiskData2.cs
public class DiskData2 : MonoBehaviour {public float size;public Color color;public float speed;public bool hit = false;public SSAction action;//记录动作
}
我们真正需要设计的只是动作和动作管理器的派生类,再看看我们的需求
public interface IActionManager
{void playDisk();
}
public class Emit : SSAction
{bool enableEmit = true;//使力作用一次,不想产生变加速运动Vector3 force;//力float startX;//起始位置public SceneController sceneControler = (SceneController)SSDirector.getInstance().currentScenceController;//引入场记// Use this for initializationpublic override void Start () {startX = 6 - Random.value * 12;this.transform.position = new Vector3(startX, 0, 0);force = new Vector3(6 * Random.Range(-1, 1), 6 * Random.Range(0.5f, 2), 13 + 2 * sceneControler.round);//根据轮数设置力的大小}public static Emit GetSSAction(){Emit action = ScriptableObject.CreateInstance<Emit>();return action;}public override void Update(){//}public void Destory()//回调函数{this.destroy = true;this.callback.SSActionEvent(this);}// Update is called once per framepublic override void FixedUpdate () {if(!this.destroy){if(enableEmit){gameobject.GetComponent<Rigidbody>().velocity = Vector3.zero;gameobject.GetComponent<Rigidbody>().AddForce(force, ForceMode.Impulse);enableEmit = false;}}}
}
public class physicsManager : SSActionManager, ISSActionCallback, IActionManager
{public SceneController sceneController;//场记public DiskFactory diskFactory;//游戏工厂public Recorder scoreRecorder;//记分员public Emit EmitDisk;public GameObject Disk;int count = 0;// Use this for initializationprotected void Start(){sceneController = (SceneController)SSDirector.getInstance().currentScenceController;diskFactory = sceneController.factory;scoreRecorder = sceneController.scoreRecorder;sceneController.actionManager = this;//设置动作管理器}// Update is called once per frameprotected new void Update(){if (sceneController.round <= 3 && sceneController.game == 1)//游戏总轮数为3轮{count++;if (count == 60)//每60帧发射一个飞碟{playDisk();sceneController.num++;//print(sceneController.num);count = 0;}base.Update();}}public void playDisk(){EmitDisk = Emit.GetSSAction();Disk = diskFactory.getDisk(sceneController.round);this.RunAction(Disk, EmitDisk, this);Disk.GetComponent<DiskData2>().action = EmitDisk;}public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,int intParam = 0, string strParam = null, Object objectParam = null) //回调函数回收飞碟记录是否失分{if (!source.gameobject.GetComponent<DiskData2>().hit)scoreRecorder.miss();diskFactory.freeDisk(source.gameobject);source.gameobject.GetComponent<DiskData2>().hit = false;}
}
public class Check : MonoBehaviour {public int num;public Emit EmitDisk;void OnTriggerEnter(Collider other){Debug.Log(other.gameObject.tag);if (other.gameObject.tag == "Disk"){EmitDisk = (Emit)other.gameObject.GetComponent<DiskData2>().action;EmitDisk.Destory();}}
}
Unity3D学习(7)之物理引擎的应用与代码复用相关推荐
- 【Unity3d学习】使用物理引擎——打飞碟游戏的物理引擎改进与射箭游戏设计
文章目录 写在前面 HitUFO的物理引擎改进版本 物理引擎的改进版本思路与实现 PhysicsAction PhysicsManager 新接口类IActionManager 动作管理器基类的变化 ...
- 【Unity3D入门教程】物理引擎之碰撞解析
Unity3D内置物理引擎,可以模拟物理效果.典型的一个物理效果就是碰撞.本文将会针对最简单的案例讲述Unity3D的碰撞规律. 1 碰撞规律 首先在场景中创建一个Sphere和一个Cube,它们都是 ...
- python 物理引擎 摩擦力_Python 愤怒的小鸟代码实现:物理引擎pymunk使用
游戏介绍 最近比较忙,周末正好有时间写了python版本的愤怒的小鸟,使用了物理引擎pymunk,图片资源是从github上下载的,实现了一个可玩的简单版本. 功能实现如下:支持小鸟类型:红色小鸟,蓝 ...
- three.js学习笔记(十)——物理引擎
我们可以利用数学函数和一些解决方案像RayCaster来实现自己的物理效果,但是如果需求更加真实的物理效果,像是物体张力.摩擦力.拉伸.反弹等真实物理效果,最好使用外部库 原理 我们会创建一个Thre ...
- Unity学习第一周-物理引擎-项目——坦克大战单机版
项目需求及策划
- unity 下一帧执行_Unity中的Havok Physics物理引擎
在GDC 2019上,我们宣布将Havok Physics作为预览版资源包加入到Unity资源包管理器,这意味着所有Unity开发者都可以使用这款知名的物理引擎.在当今主机平台中,Havok Phys ...
- 关于物理引擎的使用,及其重力感应的小test
好久没写博文了,过去那些天比较忙,一直在做点别的东西,不过作为小菜的我也不忘记学习,现在跟大家分享下我的小知识吧! 首先建立个带有box2d物理引擎的项目,在头文件中加入 public:// Here ...
- Unity3d学习 第一天 使用Unity3d的物理引擎制作 小球打砖块 游戏
做一个打砖块的游戏,最终的结果是如下图所示 这个游戏很简单,主要就是利用了Unity3d的物理引擎,有兴趣的朋友可以先自己做一下,游戏虽然简单,但我中间遇到很多坑,看看有没有人能一下做好. 一.创建四 ...
- Unity3D游戏开发初探—3.初步了解U3D物理引擎
一.什么是物理引擎? 四个世纪前,物理学家牛顿发现了万有引力,并延伸出三大牛顿定理,为之后的物理学界的发展奠定了强大的理论基础.牛顿有句话是这么说的:"如果说我看得比较远的话,那是因为我站在 ...
最新文章
- NLP深度学习:近期趋势概述
- VMware Workstations三种网卡模式
- 贪心算法之——独木舟上的旅行(nyoj71)
- Visual Basic 15语言新特性
- 远程计算机需要网络级别身份验证,而您的计算机不支持该验证,请联系您的系统管理员或者技术人员来获得帮助...
- 【HDU - 1937 】Finding Seats(二维前缀和+尺取法)
- 使用pymysql进行数据库的增删改查
- android向h5传递参数,H5与安卓传递多个参数
- C语言小游戏,游戏设计,500+行代码
- MATLAB除法运算的精度问题及其解决方案
- matlab的小波分析,matlab小波分析步骤是什么
- 人工智能的现状与未来(附PPT)
- springboot读取文件
- android launcher启动过程,Android应用启动过程-Launcher源码浅析
- SpringCloud与微服务Ⅴ --- Eureka服务注册与发现
- 家庭教育的重要性,家庭教育是一切教育的基石
- 头牌知产介绍空气炸锅商标转让类别
- 英国内政大臣:科技公司给信息加密不可接受
- 关于DebugView无法打印出KdPrint信息
- 图像处理课程大设计--汽车牌照自动识别