这次做一个有点类似飞碟射击的游戏,射箭游戏
规则:靶有五环,射中不同的靶会相应加不同的分数(从红心到最外环分别加100,70,50,40,30,20),射出靶外会扣分200,中靶10次会有一次神箭效果(蓄满了能量),神箭中靶会相应加十倍分数而且会有特效,鼠标移动弓,而且每3秒变换一次风向,风向只有东风和西方,影响箭的飞向,所以要有预判能力。
先上效果图:
游戏架构跟飞碟的差不多,如下:
接下来讲讲靶和箭的制作:
靶的制作方法是用一个空物体装六个圆柱体,越内环越厚,半径越小,越外环越薄,半径越大(如图),这是组合模式,然后只在根物体上加刚体,C0到C5不加刚体但加网格碰撞器
就这样一个靶就形成了。
接下来是箭:
也是组合模式:根物体加刚体和网格碰撞器就行,子物体都不用加,body是圆柱体,箭头我用两个方块做
是不是看起来也挺疼的~~~
还有弓的模型我是在商店下载的,再直接拿来做预设
讲讲实现细节:弓跟着鼠标位置移动,只需要不断刷新弓的位置就行,射箭出去的实现跟射飞碟差不多,然后箭怎么停留在靶上呢?有一个技巧,可以用触发器把箭的刚体去掉,这样箭就会停留在靶上,至于神箭特效,就是简单加个爆炸粒子而已。看起来挺帅,是不是实现挺简单的?
接下来上代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Director : System.Object
{
private static Director _instance;
public SceneController _Controller { get; set; }
public static Director getinstance()
{
if (_instance == null)
{
_instance = new Director();
}
return _instance;
}
public int getFPS()
{
return Application.targetFrameRate;
}
public void setFPS(int fps)
{
Application.targetFrameRate = fps;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Recorder : MonoBehaviour {
private int _score = 0;
void Start() {}
public void AddScore(string _circle,bool full)//根据环的名字加相应分数,full判断是否神箭
{
Debug.Log(full);
if (_circle == "C0") {
if (full) _score += 1000;
else _score += 100;
}
else if (_circle == "C1") {
if (full) _score += 700;
else _score += 70;
}
else if (_circle == "C2") {
if (full) _score += 500;
else _score += 50;
}
else if (_circle == "C3") {
if (full) _score += 400;
else _score += 40;
}
else if (_circle == "C4") {
if (full) _score += 300;
else _score += 30;
}
else if (_circle == "C5") {
if (full) _score += 200;
else _score += 20;
}
else if (_circle == "Plane") _score -= 200;
}
public int getScore() { return _score; }
void Update () {
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class UserFace : MonoBehaviour {
private SceneController _Controller;
public Camera _camera;
public Text Score;
public Text WindForce;
public Text WindDir;
public Text energy;
private float tempwind;
private GameObject bow;
public Vector3 bowpos;
void Start () {
_Controller = (SceneController)FindObjectOfType(typeof(SceneController));
bow = Instantiate(Resources.Load("Prefabs/Bow")) as GameObject;
}
void Update () {
bowpos = new Vector3(Input.mousePosition.x - 473, Input.mousePosition.y - 300, -7);//不断刷新弓的位置
bow.transform.position = bowpos;
tempwind = _Controller.getActionManager().getWingForce();//获取风力然后显示风向以及力度
if (tempwind>0f)
{
WindDir.text = "WindDirection:EAST";
WindForce.text = "WindForce:" + tempwind;
} else if(tempwind<0f)
{
tempwind = -tempwind;
WindDir.text = "WindDirection:WEST";
WindForce.text = "WindForce:" + tempwind;
} else
{
WindForce.text = "WindForce:" + tempwind;
WindDir.text = "WindDirection:NoWind";
}
if (Input.GetMouseButtonDown(0))
{
Ray mouseRay = _camera.ScreenPointToRay(Input.mousePosition);
_Controller.shootArrow(mouseRay.direction,bowpos);
}
Score.text = "Score:" + _Controller.getRecorder().getScore();
energy.text = "Energy:" + _Controller.goalcount*10 + "%";
}
}
箭工厂跟飞碟工厂差不多
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ArrowFactory : MonoBehaviour {
public List Using; //储存使用中的箭矢
public List Used; //储存空闲箭矢
private GameObject arrowPrefab;
void Start () {
arrowPrefab = Instantiate(Resources.Load("Prefabs/arrow")) as GameObject;
Using = new List();
Used = new List();
}
public GameObject getArrow()
{
GameObject t;
if (Used.Count == 0)
{
t = GameObject.Instantiate(arrowPrefab);
t.SetActive(true);
}
else
{
t = Used[0];
t.SetActive(true);
Used.Remove(t);
if (t.GetComponent() == null)
t.AddComponent();
Component[] comp = t.GetComponentsInChildren();
foreach (CapsuleCollider i in comp)
{
i.enabled = true;
}
t.GetComponent().isTrigger = true;
}
Using.Add(t);
return t;
}
private void freeArrow()
{
for (int i = 0; i < Using.Count; i++)
{
GameObject t = Using[i];
if (!t.activeInHierarchy)
{
Using.RemoveAt(i);
Used.Add(t);
}
}
}
void Update () {
freeArrow();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ArrowModule : MonoBehaviour {
private string circle="";
private float _time = 8f;
private SceneController _Controller;
public ParticleSystem _exposion;
void OnTriggerEnter(Collider other)
{
if(circle=="")
{
circle = other.gameObject.name;
Debug.Log(circle);
if(circle!="Plane")
{
if(_Controller.goalcount==10)//是神箭
{
_Controller.goalcount = 0;
_Controller.energyflag = true;
_exposion.transform.position = other.transform.position;
_exposion.Play();//播放神箭特效
} else
_Controller.goalcount++;
}
Destroy(GetComponent());
Component[] comp = GetComponentsInChildren();//把箭的碰撞器取消以免与其他箭碰撞
foreach (CapsuleCollider i in comp)
{
i.enabled = false;
}
GetComponent().isTrigger = false;//防止箭再次触发
_Controller.getRecorder().AddScore(circle, _Controller.energyflag);
_Controller.energyflag = false;
}
}
void Start () {
_Controller = (SceneController)FindObjectOfType(typeof(SceneController));
_exposion = GameObject.Instantiate(_exposion) as ParticleSystem;
}
void Update () {
if (_time > 0) _time -= Time.deltaTime;
else if(_time<=0)
{
this.gameObject.SetActive(false);
_time = 8f;
circle = "";
}
}
}
SceneController以及动作管理器和飞碟的比较相似
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SceneController : MonoBehaviour {
private ActionManager _Manager;
private Recorder _Recorder;
private ArrowFactory _Factory;
public bool energyflag = false;
public int goalcount=0;
void Start()
{
Director _director = Director.getinstance();
_director._Controller = this;
_Manager = (ActionManager)FindObjectOfType(typeof(ActionManager));
_Recorder = (Recorder)FindObjectOfType(typeof(Recorder));
_Factory = (ArrowFactory)FindObjectOfType(typeof(ArrowFactory));
_director.setFPS(60);
_director._Controller = this;
}
public ArrowFactory getFactory()
{
return _Factory;
}
public Recorder getRecorder()
{
return _Recorder;
}
public ActionManager getActionManager()
{
return _Manager;
}
public void shootArrow(Vector3 dir,Vector3 bowpos)
{
GameObject arrow = _Factory.getArrow();
arrow.transform.position = bowpos;
_Manager.shoot(arrow, dir);
}
void Update () {
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ActionManager : MonoBehaviour {
private SceneController _Controller;
float _windforce = 0f;
float _speed = 40f;
private bool ischangewind = true;
float _time = 3f;
void Start () {
_Controller = (SceneController)FindObjectOfType(typeof(SceneController));
}
public void shoot(GameObject _arrow,Vector3 _dir)
{
_arrow.transform.up = _dir;
_arrow.GetComponent().velocity = _dir * _speed;
}
public void WindSystem() //风力系统,每3秒变一次
{
for(int i=0;i< _Controller.getFactory().Using.Count;i++)
{
if(_Controller.getFactory().Using[i].activeInHierarchy&& _Controller.getFactory().Using[i].GetComponent())
{
_Controller.getFactory().Using[i].GetComponent().AddForce(new Vector3(_windforce, 0, 0), ForceMode.Force);
}
}
}
public float getWingForce() { return _windforce; }
private void setForce()
{
if(ischangewind)
{
_windforce = Random.Range(-30f, 30f);
ischangewind = false;
}
}
void Update () {
if (_time > 0) _time -= Time.deltaTime;
else if(_time<=0)
{
ischangewind = true;
_time = 3f;
}
WindSystem();
setForce();
}
}