Unity 群聚(生成鱼群)

  • 游戏简介

实验以捕鱼达人为基础,生成不同种类型的鱼群,每个鱼群都有独立的特征,比如外观,游向,速度等等,鱼群中的每个个体又有自己独特的性质,但他们都跟随父物体移动,有自己微小的变化,但总体趋势和父物体一致。在游戏中首先是创建一个2D的sprite来制作背景,然后创建一个空物体来随机生成鱼,鱼生成的位置始终是在背景图片下,之后才是鱼群的制作,以及鱼群的特征。

  • 游戏的整体框架

游戏就是由简单的两部分组成,一部分是背景图片,一部分是随机生成鱼,其中BG是一个sprite,Spawner是一个空物体,用来随机生成鱼。

  • 游戏实现

1、首先是游戏背景的设置,首先创建一个2D的sprite,然后找到一张大海的图片赋予sprite,并调整图片的大小,使图片全屏显示,效果如下

2、资源导入以及预制体的制作,在资源商店中下载一个鱼的资源导入,由于版本和付费的限制,这里下载的是Sardine,其中鱼的类型如下,我们需要的是会游动的鱼,所以选择了资源里的第三种鱼。把第三个鱼拖到场景中,通过更改鱼的外观,设置三条不同颜色的鱼,并分别把他们设置成预制体,新建一个文件夹来存储他们。

        

3、在背景范围内生成鱼。新建一个空物体,命名为Spawner,编写代码赋给Spawner,其中限制了鱼的数量上限,设置成公有成员,在游戏场景中可以修改,鱼生成后开始向左移动,代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Spawner : MonoBehaviour
{
    public GameObject []fishPrefabs;
    public float timeInterval = 1;
    private float timer = 0;//定时器
    private int currentcount = 0;//当前鱼塘中鱼的数量
    public int maxCount = 10;//鱼塘中鱼的上限
    private Transform Bg;//背景图片
    // Start is called before the first frame update
    void Start()
    {
        Bg = GameObject.Find("BG").transform;
    }
    // Update is called once per frame
    void Update()
    {
        //判断鱼塘是否饱和
        if (currentcount >= maxCount)
        {
            return;
        }
        CreateFish();
    }
    void CreateFish()
    {
        timer += Time.deltaTime;//计时
        if (timer >= timeInterval)
        {
            currentcount++;
            timer -= timeInterval;
          
                GameObject go = fishPrefabs[Random.Range(0, fishPrefabs.Length)];
            //随机视口坐标系的点
         
                Vector3 viewPort = new Vector3(Random.value, Random.value, 0);
            Vector3 worldPoint = Camera.main.ViewportToWorldPoint(viewPort);
            worldPoint.z = Bg.position.z-1;  //使得鱼和背景处于同一个xy平面
            //实例化
          
                Instantiate(go, worldPoint, go.transform.rotation);

            
        }
    }
}

4、鱼群的生成,生成一群鱼,并使他们在父物体的引导下移动,每个鱼群个体又有自己独立的行为重新编写代码,赋给Spawner,原有的脚本要删除,在游戏中把预制体赋给对象,全新代码如下:

using UnityEngine;
using System.Collections;

public class SardineBoidsController : MonoBehaviour {
	public GameObject sardinePrefab;
 	GameObject[] sardines;
	public int maxXNum=2;
	public int maxYNum=3;
	public int maxZNum=4;
	public Vector3 meanPos;
	public int sardineCount;
	public float rotateSpeed=1f;
	public GameObject meanDummy;

	void Start () {
		sardineCount = maxZNum *maxYNum* maxXNum;
		sardines = new GameObject[sardineCount];
		for (int k=0; k<maxZNum; k++) {
			for (int j=0; j<maxYNum; j++) {
				for (int i=0; i<maxXNum; i++) {
					int sNum=k*maxXNum*maxYNum+j*maxXNum+i;
					sardines[sNum]=(GameObject)GameObject.Instantiate (sardinePrefab, transform.position+Vector3.right*i+Vector3.up*j+Vector3.forward*k, transform.rotation);
					Collider[] cols=sardines[k*maxXNum*maxYNum+j*maxXNum+i].GetComponentsInChildren<Collider>();
					foreach(Collider col in cols){
						col.name="SardineCol";
					}
				}
			}
		}
	}

	void Update () {
		meanPos = Vector3.zero;
		for (int i=0; i<sardineCount; i++) {
			meanPos=meanPos+sardines[i].transform.position;

		}
		meanPos = meanPos / sardineCount;
		meanDummy.transform.position = meanPos;

		for (int i=0; i<sardineCount; i++) {
			Vector3 targetRelPos = meanPos - sardines[i].transform.position;
			targetRelPos.Normalize();
			float dottigawa = Vector3.Dot (targetRelPos,sardines[i].transform.right);
			 
			Rigidbody iwasirigid = sardines[i].GetComponent<Rigidbody> ();
			iwasirigid.AddTorque (sardines[i].transform.up * dottigawa*rotateSpeed);
			sardines[i].GetComponent<Animator>().SetFloat("Turn",dottigawa*rotateSpeed);

			dottigawa = Vector3.Dot (targetRelPos,sardines[i].transform.up);
			iwasirigid.AddTorque (-sardines[i].transform.right * dottigawa*rotateSpeed);
			sardines[i].GetComponent<Animator>().SetFloat("Up", dottigawa*rotateSpeed);
		}
	}
}

最终运行结果如下:

猜你喜欢

转载自blog.csdn.net/lxy20011125/article/details/129896150