Unity コンバット ターゲット ゲーム

ユニティコンバットUFOゲーム

プロジェクトのソース コード

全体的な説明

ユニティを使用してシンプルな空飛ぶ円盤ゲームを実現し、対応するターゲットにヒットするとスコアを獲得します。1ゲームで矢は5本。





デザインのアイデア

UML ダイアグラムは次のとおりです。

ここに画像の説明を挿入





コンポーネントを定義する

  1. 弓と矢

    矢じりと矢本体の 2 つの部分で構成されます。

    矢印は、コライダーを搭載する比較的小さなカプセルです。矢印本体はAssets Storeからダウンロードしたフリー素材です

    ここに画像の説明を挿入



  1. 目標

    高さの異なる5本の同心円柱で構成され、それぞれの円柱が搭載されRingData、異なる楽譜に対応

    ここに画像の説明を挿入





コード

CCShootAction: 矢の発射イベントを実装

public class CCShootAction : SSAction
{
    Vector3 force;
    Vector3 wind;

    private CCShootAction(){}

    // Start is called before the first frame update
    public override void Start()
    {
        gameObject.transform.parent = null;
        gameObject.GetComponent<Rigidbody>().velocity = Vector3.zero;

        // force = new Vector3(0, 0, 30);
        // Impulse:向此刚体添加瞬时力冲击,考虑其质量。
        gameObject.GetComponent<Rigidbody>().AddForce(force, ForceMode.Impulse);
        gameObject.GetComponent<Rigidbody>().AddForce(wind, ForceMode.Impulse);
        gameObject.GetComponent<Rigidbody>().isKinematic = false;
    }

    // Update is called once per frame
    public override void Update()
    {

    }

    public override void FixedUpdate(){
        // 箭飞到场外或者中靶
        if(this.transform.position.z > 35 || this.transform.tag == "onTarget"){
            Debug.Log("回调");
            this.destroy = true;
            this.enable = false;
            this.callback.SSActionEvent(this, SSActionEventType.Completed, 0, null, gameObject);
        }
    }

    public static CCShootAction GetSSAction(Vector3 wind){
        CCShootAction shoot = CreateInstance<CCShootAction>();
        shoot.force = new Vector3(0, 0, 40);
        shoot.wind = wind;
        return shoot;
    }
}


CCShootActionManager: アーチェリーのアクション管理を実現

public class CCShootActionManager : SSActionManager
{
    public FirstController firstController;
    public CCShootAction shoot;

    // Start is called before the first frame update
    protected void Start()
    {
        firstController = (FirstController)SSDirector.GetInstance().CurrentScenceController;
        firstController.actionManager = this;
    }

    public void Shoot(GameObject arrow, Vector3 wind){
        Debug.Log("Shoot");
        shoot = CCShootAction.GetSSAction(wind);
        this.RunAction(arrow, shoot, this);
    }
}


TrembleAction: コールバック関数で呼び出される、矢が当たった後の震えるアクション

public class TrembleAction : SSAction
{
    float tremble_radius = 0.05f;
    float tremble_time = 0.5f; 
    GameObject arrow;

    Vector3 arrow_pos;

    private TrembleAction(){}
    public static TrembleAction GetSSAction()
    {
        TrembleAction tremble_action = CreateInstance<TrembleAction>();
        return tremble_action;

    }

    // Start is called before the first frame update
    public override void Start()
    {
        //得到箭中靶时的位置
        arrow_pos = gameObject.transform.position;
        // this.transform.Translate(new Vector3(0, 0, 0.5f));
        Debug.Log(gameObject.transform.name);
    }

    // Update is called once per frame
    public override void Update()
    {   
        tremble_time -= Time.deltaTime;
        //需要继续颤抖
        if(tremble_time > 0){
            // gameObject.transform.Translate(new Vector3(0.02f, 0, 0));
           
            Vector3 head_pos = gameObject.transform.position;

            float x = arrow_pos.x + Random.RandomRange(-0.05f, 0.05f);
            float y = arrow_pos.y + Random.RandomRange(-0.05f, 0.05f);
            float z = arrow_pos.z;
            gameObject.transform.position = new Vector3(x, y, z);
        }
        else{
            gameObject.transform.position = arrow_pos;
        }
        // else{
        //     transform.position = arrow_pos;
        //     this.destroy = true;
        //     this.callback.SSActionEvent(this);
        // }
    }
}

SSActionManagerでの特定のアプリケーション

public void SSActionEvent(SSAction source,
        SSActionEventType events = SSActionEventType.Completed,
        int intParam = 0,
        string strParam = null,
        GameObject arrow = null){
            TrembleAction trembleAction = TrembleAction.GetSSAction();
            this.RunAction(arrow, trembleAction, this);
        }


ArrowFactory: 弓矢の生産とリリースに使用される矢工場

public class ArrowFactory : MonoBehaviour
{
    private List<GameObject> used;
    private List<GameObject> free;
    public GameObject arrow;
    FirstController firstController;
    // Start is called before the first frame update
    void Start()
    {
        firstController = (FirstController)SSDirector.GetInstance().CurrentScenceController;
        used = new List<GameObject>();
        free = new List<GameObject>();
        arrow = null;
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public GameObject GetArrow(){
        if(free.Count > 0){
            arrow = free[0];
            free.Remove(free[0]);
            if(arrow.tag == "onTarget")//箭在靶子上
            {
                arrow.GetComponent<Rigidbody>().isKinematic = false;
                arrow.tag = "arrow";
                arrow.transform.GetChild(0).gameObject.SetActive(true);
            }
            arrow.SetActive(true);
        }
        else{
            arrow = Instantiate(Resources.Load<GameObject>("Prefabs/arrow1"));
            arrow.GetComponent<Rigidbody>().isKinematic = false;
            // arrow.AddComponent<Rigidbody>();
        }
        // firstController = (FirstController)SSDirector.GetInstance().CurrentScenceController;
        // Transform pos = firstController.bow.transform.GetChild(0);
        // arrow.transform.position = pos.transform.position;
        arrow.transform.parent = firstController.bow.transform;   // 把arrow附加在bow上,跟随着bow移动
        arrow.transform.position = firstController.bow.transform.position;
        used.Add(arrow);

        return arrow;
    }

    public void FreeArrow(GameObject arrow){
        foreach(GameObject aa in used){
            Debug.Log("befreed");
            if(aa.gameObject.GetInstanceID() == arrow.GetInstanceID()){
                arrow.SetActive(false);
                used.Remove(aa);
                aa.tag = "arrow";
                break;
            }
        }
    }

    public void Clear(){
        foreach(GameObject dd in used){
            dd.transform.position = new Vector3(0, 0, 100);
            Destroy(dd);
        }
        foreach(GameObject dd in free){
            dd.transform.position = new Vector3(0, 0, 100);
            Destroy(dd);
        }
        used.Clear();
        free.Clear();
    }
}



RingData: 各リングに取り付けられ、異なるリングのスコアを定義するために使用されます

public class RingData : MonoBehaviour {
    public int score;

    public void Start(){
        if(this.gameObject.name=="1"){
            score = 5;
        }
        else if(this.gameObject.name=="2"){
            score = 4;
        }
        else if(this.gameObject.name=="3"){
            score = 3;
        }
        else if(this.gameObject.name=="4"){
            score = 2;
        }
        else{
            score = 1;
        }
    }
}


RingController:リングインパクトイベント、スコアリング、コールバック震えアクションを制御

public class RingController : MonoBehaviour
{
    public ScoreRecorder scoreRecorder;
    public ISceneController sceneController;
    
    // Start is called before the first frame update
    void Start()
    {
        sceneController = SSDirector.GetInstance().CurrentScenceController as FirstController;
        scoreRecorder = Singleton<ScoreRecorder>.Instance;
        this.gameObject.AddComponent<RingData>();
    }

    // Update is called once per frame
    void OnTriggerEnter(Collider arrowCollider){
        Debug.Log("碰撞!");
        Transform arrow = arrowCollider.gameObject.transform.parent;
        Debug.Log(arrow.gameObject.name);
        if(arrow == null){
            Debug.Log("null");
            return;
        }
        scoreRecorder.RecordScore(this.gameObject.GetComponent<RingData>().score);
        Debug.Log("Score:"+this.gameObject.GetComponent<RingData>().score);

        
        arrow.GetComponent<Rigidbody>().isKinematic = true;
        arrow.GetComponent<Rigidbody>().velocity = new Vector3(0, 0, 0);
        arrowCollider.gameObject.SetActive(false);
        arrow.tag = "onTarget";
    }
}

おすすめ

転載: blog.csdn.net/weixin_51930942/article/details/128179548