Unity3D学习:射箭打靶游戏

这次做一个有点类似飞碟射击的游戏,射箭游戏

规则:靶有五环,射中不同的靶会相应加不同的分数(从红心到最外环分别加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<GameObject> Using; //储存使用中的箭矢  
    public List<GameObject> Used; //储存空闲箭矢  
    private GameObject arrowPrefab;
    void Start () {
        arrowPrefab = Instantiate(Resources.Load("Prefabs/arrow")) as GameObject;
        Using = new List<GameObject>();
        Used = new List<GameObject>();
    }
    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<Rigidbody>() == null)
                t.AddComponent<Rigidbody>();
            Component[] comp = t.GetComponentsInChildren<CapsuleCollider>();
            foreach (CapsuleCollider i in comp)
            {
                i.enabled = true;
            }
            t.GetComponent<MeshCollider>().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<Rigidbody>());
            Component[] comp = GetComponentsInChildren<CapsuleCollider>();//把箭的碰撞器取消以免与其他箭碰撞
            foreach (CapsuleCollider i in comp)
            {
                i.enabled = false;
            }
            GetComponent<MeshCollider>().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<Rigidbody>().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<Rigidbody>())
            {
                _Controller.getFactory().Using[i].GetComponent<Rigidbody>().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();
    }
}
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值