首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何防止在按F改变格式时添加越来越多的新对象?

如何防止在按F改变格式时添加越来越多的新对象?
EN

Stack Overflow用户
提问于 2018-11-03 07:59:35
回答 1查看 54关注 0票数 0
代码语言:javascript
复制
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class SquadFormation : MonoBehaviour
{
    enum Formation
    {
        Square, Circle, Triangle
    }

    [Header("Main Settings")]
    [Space(5)]
    public Transform squadMemeberPrefab;
    [Range(4, 100)]
    public int numberOfSquadMembers = 20;
    [Range(1, 20)]
    public int numberOfSquads = 1;
    [Range(0, 4)]
    public int columns = 4;
    public int gaps = 10;
    public int circleRadius = 10;
    public float yOffset = 0;
    [Range(3, 50)]
    public float moveSpeed = 3;
    [Range(3, 50)]
    public float rotateSpeed = 1;
    public float threshold = 0.1f;
    public bool randomSpeed = false;
    [Range(1, 100)]
    public int randSpeedMin = 1;
    [Range(1, 100)]
    public int randSpeedMax = 1;
    public bool startRandomFormation = false;
    public string currentFormation;

    private Formation formation;
    private List<Quaternion> quaternions = new List<Quaternion>();
    private List<Vector3> newpositions = new List<Vector3>();
    private bool move = false;
    private bool squareFormation = false;
    private List<GameObject> squadMembers = new List<GameObject>();
    private float[] step;
    private int[] randomSpeeds;
    private int index = 0;
    private int numofobjects = 0;

    // Use this for initialization
    void Start()
    {
        numofobjects = numberOfSquadMembers;
        if (startRandomFormation)
        {
            formation = (Formation)UnityEngine.Random.Range(0, Enum.GetNames(typeof(Formation)).Length);
        }
        else
        {
            formation = Formation.Square;
        }
        currentFormation = formation.ToString();
        ChangeFormation();

        foreach (Transform child in gameObject.transform)
        {
            if (child.tag == "Squad Member")
                squadMembers.Add(child.gameObject);
        }

        randomSpeeds = RandomNumbers(randSpeedMin, randSpeedMax, squadMembers.Count);
        step = new float[squadMembers.Count];
    }

    // Update is called once per frame
    void Update()
    {
        if (numofobjects != numberOfSquadMembers)
        {
            numofobjects = 0;

            numofobjects = numberOfSquadMembers;
            squadMembers = new List<GameObject>();

            FormationSquare();
        }

        if (Input.GetKeyDown(KeyCode.F))
        {
            randomSpeeds = RandomNumbers(randSpeedMin, randSpeedMax, squadMembers.Count);
            foreach (int speedV in randomSpeeds)
            {
                if (index == randomSpeeds.Length)
                    index = 0;

                step[index] = speedV * Time.deltaTime;
                index++;
            }

            ChangeFormation();
        }

        if (move == true)
        {
            MoveToNextFormation();
        }
    }

    private void ChangeFormation()
    {
        switch (formation)
        {
            case Formation.Square:
                FormationSquare();
                break;

            case Formation.Circle:
                FormationCircle();
                break;
        }
    }

    private Vector3 FormationSquarePositionCalculation(int index) // call this func for all your objects
    {
        float posX = (index % columns) * gaps;
        float posY = (index / columns) * gaps;
        return new Vector3(posX, posY);
    }

    private void FormationSquare()
    {
        newpositions = new List<Vector3>();
        quaternions = new List<Quaternion>();

        Transform go = squadMemeberPrefab;

        for (int i = 0; i < numofobjects; i++)
        {
            if (squadMembers.Count == 0)
                go = Instantiate(squadMemeberPrefab);

            Vector3 pos = FormationSquarePositionCalculation(i);

            go.position = new Vector3(transform.position.x + pos.x, 0, transform.position.y + pos.y);
            go.Rotate(new Vector3(0, -90, 0));
            go.tag = "Squad Member";
            go.transform.parent = gameObject.transform;
            newpositions.Add(go.transform.position);
        }
        move = true;
        squareFormation = true;
        formation = Formation.Circle;
    }

    private Vector3 FormationCirclePositionCalculation(Vector3 center, float radius, int index, float angleIncrement)
    {
        float ang = index * angleIncrement;
        Vector3 pos;
        pos.x = center.x + radius * Mathf.Sin(ang * Mathf.Deg2Rad);
        pos.z = center.z + radius * Mathf.Cos(ang * Mathf.Deg2Rad);
        pos.y = center.y;
        return pos;
    }

    private void FormationCircle()
    {
        newpositions = new List<Vector3>();
        quaternions = new List<Quaternion>();

        Vector3 center = transform.position;
        float radius = (float)circleRadius / 2;
        float angleIncrement = 360 / (float)numberOfSquadMembers;
        for (int i = 0; i < numberOfSquadMembers; i++)
        {
            Vector3 pos = FormationCirclePositionCalculation(center, radius, i, angleIncrement);

            var rot = Quaternion.LookRotation(center - pos);
            pos.y = Terrain.activeTerrain.SampleHeight(pos);
            pos.y = pos.y + yOffset;
            newpositions.Add(pos);
            quaternions.Add(rot);
        }
        move = true;
        squareFormation = false;
        formation = Formation.Square;
    }

    private void MoveToNextFormation()
    {
        if (randomSpeed == false)
        {
            if (step.Length > 0)
                step[0] = moveSpeed * Time.deltaTime;
        }

        for (int i = 0; i < squadMembers.Count; i++)
        {
            squadMembers[i].transform.LookAt(newpositions[i]);
            if (randomSpeed == true)
            {
                squadMembers[i].transform.position =
            Vector3.MoveTowards(squadMembers[i].transform.position, newpositions[i], step[i]);
            }
            else
            {
                squadMembers[i].transform.position =
                Vector3.MoveTowards(squadMembers[i].transform.position, newpositions[i], step[0]);
            }
            if (Vector3.Distance(squadMembers[i].transform.position, newpositions[i]) < threshold)
            {
                if (squareFormation == true)
                {
                    Vector3 degrees = new Vector3(0, 0, 0);
                    Quaternion quaternion = Quaternion.Euler(degrees);
                    squadMembers[i].transform.rotation = Quaternion.Slerp(squadMembers[i].transform.rotation, quaternion, rotateSpeed * Time.deltaTime);
                }
                else
                {
                    squadMembers[i].transform.rotation = Quaternion.Slerp(squadMembers[i].transform.rotation, quaternions[i], rotateSpeed * Time.deltaTime);
                }
            }
        }
    }

    private static int[] RandomNumbers(int min, int max, int howMany)
    {
        int[] myNumbers = new int[howMany];

        for (int i = 0; i < howMany; i++)
        {
            myNumbers[i] = UnityEngine.Random.Range(min, max);
        }

        return myNumbers;
    }
}

在构造函数中,我使用标记团队成员搜索childs。但是列表squadMembers将是空的,因为脚本附加到一个新的空GameObject上,没有任何子程序。

然后变量步骤也将为空。然后,在方法MoveToNextFormation中,我正在检查step是否为空:

代码语言:javascript
复制
if (step.Length > 0)
                step[0] = moveSpeed * Time.deltaTime;

如果不检查它将抛出异常,因为索引0没有任何异常,则为null。但是如果台阶是空的,那么物体的运动就没有速度/s了。

这是个问题。我甚至不知道为什么在构造函数中,我与孩子和“团队成员”标签一起做了这个角色。我还没有用这个标记创建任何子元素,所以我对我试图在构造函数中做什么感到困惑。

第二个问题在FormationSquare方法的这一行中:

代码语言:javascript
复制
if (squadMembers.Count == 0)
                go = Instantiate(squadMemeberPrefab);

但是如果squadMembers是空的,那么它将在代码中的其他地方抛出异常。我在FormationSquare方法中创建新对象,这是因为我默认使用FormationSquare启动,但是如果我想默认情况下使用FormationCircle方法启动呢?

这个想法是从最少的(1)小队数和最少(4)成员的人数开始时开始计划。或者从最小到最大的范围开始。但一切都搞砸了。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-11-04 14:21:04

在您的示例中,我会将预编实例化与小组形状格式分开,这样做将有助于您识别错误。

例如,添加以下方法并在“开始”期间使用它们:

代码语言:javascript
复制
void AddSquadMember() 
{
   // Use this to instantiate/spawn a new game object prefab.
}

void AddSquadMember(GameObject object) 
{
   // Use this for game object already in the scene. (.eg the children with your tag)
}

然后,在形成方法上,删除语调调用,只使用列表中的任何游戏对象。

最后,我会抛出“numofobjects”变量。然后使用“squadMembers.Count”而不是“numofobjects”和“numberOfSquadMembers”,假设在“开始”期间,您已经负责实例化所有游戏对象,以便“numberOfSquadMembers == squadMembers.Count”。这是因为你可能需要在游戏中增加几个成员来提高阵容。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53129518

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档