嗨,我是 unity 的新手,这是我第一次尝试在上面制作我自己的程序,所以除了我的问题之外的任何其他提示也将不胜感激:)
我正在使用 unity 制作一个程序,该程序使用简单的遗传算法从平台的一侧到另一侧得到一个正方形(ai) 一旦它经历了一代并确定向右移动是最好的并且所有新的实例化预制件都被创建并且 Aimovement 列表变量设置为向右移动(如代码一侧的数字 1 所示) 在第 2 点,一切都是正确的,直到这个 for 循环应该给每个 ai 一个单独的额外随机移动但是每次它执行时: instanceScipt.AiMovements.Add(possibleMovements[randomNum]); 它将那个移动添加到每个 ais 脚本变量,然后进入下一个已经添加了一个的 ai,然后添加另一个,问题重复,所以在循环结束时,每个 ai 本来只是为了获得随机移动相反,添加了 10 个动作,并且与其他所有 ai 完全相同。
主控脚本-附加到空对象
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AiManager : MonoBehaviour
{
public GameObject AiPrefab;
private string[] possibleMovements = { "MoveRight", "MoveLeft", "Jump" };
public int startingAiNum = 50;
public int currentAiNum;
public int generation = 1;
public List<GameObject> Ais = new List<GameObject>();
private bool completed = false;
private int waiting = 200;
public float sideSpeed = 2f;
public float jumpSpeed = 4f;
public int movementNum = 0;
private Vector2 velocityCheck = new Vector2(0f, 0f);
private Rigidbody2D randomAiRb;
public List<string> optimalMovements;
private void Awake()
{
for (int turn = 0; turn < startingAiNum; turn++)
{
GameObject newInstance = Instantiate(AiPrefab) as GameObject;
Ais.Add(newInstance);
GenerateMovement(turn);
}
currentAiNum = startingAiNum;
}
// Update is called once per frame
void Update()
{
if (waiting < 200)
{
waiting++;
}
else
{
randomAiRb = Ais[Random.Range(0, Ais.Count)].GetComponent<Rigidbody2D>();
waiting = 0;
for (int turn = 0; turn < currentAiNum; turn++)
{
Rigidbody2D AiRigidBody = Ais[turn].GetComponent<Rigidbody2D>();
if (AiRigidBody.transform.position.x < -6f)
{
GameObject placeHolderAi = Ais[turn];
//Ais[turn].active = false;
Ais.Remove(placeHolderAi);
Destroy(placeHolderAi);
currentAiNum--;
turn--;
continue;
}
AiAtributes instancesScipt = Ais[turn].GetComponent<AiAtributes>();
if (movementNum < instancesScipt.AiMovements.Count)
{
CompleteMovement(turn, movementNum);
if (turn == currentAiNum - 1)
{
movementNum++;
}
}
else if (movementNum >= instancesScipt.AiMovements.Count - 1
&& (randomAiRb.velocity.x != 0 && randomAiRb.velocity.y != 0)
&& (turn == currentAiNum - 1))
{
if (turn == currentAiNum - 1)
{
movementNum++;
}
}
else if (turn == currentAiNum - 1)
{
currentAiNum = startingAiNum;
movementNum = 0;
generation++;
CalculateBestMovements();
*1 ResetAis();
print("here");
break;
}
}
}
}
private void GenerateMovement(int turn)
{
AiAtributes instancesScipt = Ais[turn].GetComponent<AiAtributes>();
//
int randomNum = Random.Range(0, 3);
//
instancesScipt.AiMovements.Add(possibleMovements[randomNum]);
}
private void CompleteMovement(int turn, int movement_Num)
{
AiAtributes instancesScipt = Ais[turn].GetComponent<AiAtributes>();
//instancesScipt.AiMovements
string movement = instancesScipt.AiMovements[movement_Num];
Rigidbody2D AiRB = Ais[turn].GetComponent<Rigidbody2D>();
if (movement == "MoveRight")
{
AiRB.velocity = new Vector2(AiRB.velocity.x + sideSpeed, AiRB.velocity.y);
}
else if (movement == "MoveLeft")
{
AiRB.velocity = new Vector2(AiRB.velocity.x + -sideSpeed, AiRB.velocity.y);
}
else
{
AiRB.velocity = new Vector2(AiRB.velocity.x, AiRB.velocity.y + jumpSpeed);
}
}
private void ResetAis()
{
for (int turn = 0; turn < currentAiNum; turn++)
{
GameObject placeHolderAi = Ais[0];
Ais.Remove(placeHolderAi);
Destroy(placeHolderAi);
}
Ais = new List<GameObject>();
for (int turn = 0; turn < startingAiNum; turn++)
{
GameObject newInstance = Instantiate(AiPrefab) as GameObject;
newInstance.name = "Ai" + turn.ToString();
Ais.Add(newInstance);
AiAtributes instancesScipt = Ais[turn].GetComponent<AiAtributes>();
instancesScipt.AiMovements = optimalMovements;
}
*2 for (int turn = 0; turn < startingAiNum; turn++)
{
GenerateMovement(turn);
}
currentAiNum = startingAiNum;
}
private void CalculateBestMovements()
{
float bestFitness = -10000f;
for (int turn = 0; turn < currentAiNum; turn++)
{
AiAtributes instancesScipt = Ais[turn].GetComponent<AiAtributes>();
float fitness = Ais[turn].transform.position.x * 15f;
if (instancesScipt.collectedCoin)
{
fitness = fitness + 120f;
}
else if (instancesScipt.finished)
{
fitness = fitness + 1000000f;
}
if (fitness > bestFitness)
{
bestFitness = fitness;
optimalMovements = instancesScipt.AiMovements;
}
}
}
}
脚本附加到每个实例
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AiAtributes : MonoBehaviour
{
public List<string> AiMovements = new List<string>();
public bool finished = false;
public bool collectedCoin = false;
private void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.name == "Finish")
{
finished = true;
}
}
}
a 已经放置了很多打印语句来找出正在发生的事情,以便能够挑出 for 循环(用 astrix 和 a 2 标记)是问题所在 目前我给每个实例一个名字,以确定当脚本在 generatemovement 过程中打开时,它正在对每个单独的 ai 执行此操作,据我所知它们没有合并或其他什么 但我不知道为什么会这样,在网上找不到任何帮助或解释为什么会这样。
感谢您的帮助。