Move GameObject to Point A to B
I have the MapBrain.cs script:
public class MapBrain : MonoBehaviour
{
//Genetic Algorithm Parameters
[SerializeField, Range(20,100)]
private int populationSize = 20;
[SerializeField, Range(0,100)]
private int crossoverRate = 100;
private double crossoverRatePercent;
[SerializeField, Range(0,100)]
private int mutationRate = 0;
private double mutationRatePercent;
[SerializeField, Range(1,100)]
private int generationLimit = 10;
//Algorithm Variables
private List<CandidateMap> currentGeneration;
private int totalFitnessThisGeneration, bestFitnessScoreAllTime = 0;
private CandidateMap bestMap = null;
private int bestMapGenerationNumber = 0, generationNumber = 1;
//Fitness Parameters
[SerializeField]
private int fitnessCornerMin = 6, fitnessCornerMax = 12;
[SerializeField, Range(1,3)]
private int fitnessCornerWeight = 1, fitnessNearCornerWeight = 1;
[SerializeField, Range(1,5)]
private int fitnessPathWeight = 1;
//Map Start Parametes
[SerializeField, Range(3,20)]
private int widthOfMap = 11, lengthOfMap = 11;
private Vector3 startPosition, exitPosition;
private MapGrid grid;
[SerializeField]
private Direction startPositionEdge = Direction.Left, exitPositionEdge = Direction.Right;
[SerializeField]
private bool randomStartAndEnd = false;
[SerializeField, Range(4,9)]
private int numberOfKnightPieces = 7;
//Visualize Grid
public MapVisualizer mapVisualizer;
DateTime startDate, endDate;
private bool isAlgorithmRunning = false;
//Spawn Manager
public Transform enemyPrefab;
public bool IsAlgorithmRunning { get => isAlgorithmRunning; }
//Loading part
private void Start()
{
mutationRatePercent = mutationRate / 100D;
crossoverRatePercent = crossoverRate / 100D;
}
//Creates the scene
public void RunAlgorithm()
{
UiController.instance.ResetScreen();
UiController.instance.HideStartButton();
UiController.instance.showLevelButton();
ResetAlgorithmVariables();
mapVisualizer.ClearMap();
grid = new MapGrid(widthOfMap, lengthOfMap);
MapHelper.RandomlyChooseAndSetStartAndExit(grid, ref startPosition, ref exitPosition, randomStartAndEnd, startPositionEdge, exitPositionEdge);
isAlgorithmRunning = true;
startDate = DateTime.Now;
FindOptimalSolution(grid);
Debug.Log(EnemyDestination());
InvokeRepeating("InstantiateEnemy", 5f, 5f);
}
//Reset the algorithm to place a new level
public void ResetAlgorithmVariables()
{
totalFitnessThisGeneration = 0;
bestFitnessScoreAllTime = 0;
bestMap = null;
bestMapGenerationNumber = 0;
generationNumber = 0;
}
/*
It will create several maps,
according to the size of the population,
where it will go through the Genetic Algorithm and will return only the one with the best score
*/
public void FindOptimalSolution(MapGrid grid)
{
currentGeneration = new List<CandidateMap>(populationSize);
for (int i = 0; i < populationSize; i++)
{
var candidateMap = new CandidateMap(grid, numberOfKnightPieces);
candidateMap.CreateMap(startPosition, exitPosition, true);
currentGeneration.Add(candidateMap);
}
StartCoroutine(GeneticAlgorithm());
}
/*
Genetic Algorithm:
function GeneticAlgorithm(population, objective/function) exit: individual
Enter: population→ list of individual = CandidateMap
objective/function→ a function that receives an individual and returns a real number. = bestFitnessScoreThisGeneration
repeat = foreach (var candidate in currentGeneration)
list of parents := selection(population, objective/function) = CrossOverParents(parent1, parent2, out child1, out child2)
population: = reproduction (list of parents) = List<CandidateMap> nextGeneration = new List<CandidateMap>()
*/
private IEnumerator GeneticAlgorithm()
{
totalFitnessThisGeneration = 0;
int bestFitnessScoreThisGeneration = 0;
CandidateMap bestMapThisGeneration = null;
foreach (var candidate in currentGeneration)
{
//FindPath() = Finds a path between the generated obstacles
candidate.FindPath();
//Repair() = If there is a blocked path (Knight), repair
candidate.Repair();
var fitness = CalculateFitness(candidate.ReturnMapData());
totalFitnessThisGeneration+= fitness;
if(fitness> bestFitnessScoreThisGeneration)
{
bestFitnessScoreThisGeneration = fitness;
bestMapThisGeneration = candidate;
}
}
if(bestFitnessScoreThisGeneration > bestFitnessScoreAllTime)
{
bestFitnessScoreAllTime = bestFitnessScoreThisGeneration;
bestMap = bestMapThisGeneration.DeepClone();
bestMapGenerationNumber = generationNumber;
}
generationNumber++;
yield return new WaitForEndOfFrame();
//Loading Values
UiController.instance.SetLoadingValue(generationNumber / (float)generationLimit);
//Debug.Log("Current generation "+generationNumber+" score: "+bestMapThisGeneration);
if(generationNumber < generationLimit)
{
List<CandidateMap> nextGeneration = new List<CandidateMap>();
while(nextGeneration.Count < populationSize)
{
var parent1 = currentGeneration[RouletteWheelSelection()];
var parent2 = currentGeneration[RouletteWheelSelection()];
CandidateMap child1, child2;
CrossOverParents(parent1, parent2, out child1, out child2);
child1.AddMutation(mutationRatePercent);
child2.AddMutation(mutationRatePercent);
nextGeneration.Add(child1);
nextGeneration.Add(child2);
}
currentGeneration = nextGeneration;
StartCoroutine(GeneticAlgorithm());
}
else
{
ShowResults();
}
}//End GeneticAlgorithm
//Just shows interesting data and help mount the loading
private void ShowResults()
{
isAlgorithmRunning = false;
//Debug.Log("Best solution at generation "+bestMapGenerationNumber+" with score: "+bestFitnessScoreAllTime);
var data = bestMap.ReturnMapData();
mapVisualizer.VisaulizeMap(bestMap.Grid,data);
UiController.instance.HideLoadingScreen();
//Debug.Log("Path length: "+data.path);
//Debug.Log("Corners count: "+data.cornersList.Count);
endDate = DateTime.Now;
long elapsedTicks = endDate.Ticks - startDate.Ticks;
TimeSpan elapsedSpan = new TimeSpan(elapsedTicks);
//Debug.Log("Time need to run this genetic optimisation: "+elapsedSpan.TotalSeconds);
}
//Mix The Genes
private void CrossOverParents(CandidateMap parent1, CandidateMap parent2, out CandidateMap child1, out CandidateMap child2)
{
child1 = parent1.DeepClone();
child2 = parent2.DeepClone();
if(Random.value < crossoverRatePercent)
{
int numBits = parent1.ObstaclesArray.Length;
int crossOverIndex = Random.Range(0, numBits);
for (int i = crossOverIndex; i < numBits; i++)
{
child1.PlaceObstacle(i, parent2.IsObstacleAt(i));
child2.PlaceObstacle(i, parent1.IsObstacleAt(i));
}
}
}
//RouletteWheelSelection = Fitness proportionate selection
private int RouletteWheelSelection()
{
int randomValue = Random.Range(0, totalFitnessThisGeneration);
for (int i = 0; i < populationSize; i++)
{
randomValue -= CalculateFitness(currentGeneration[i].ReturnMapData());
if(randomValue <= 0)
{
return i;
}
}
return populationSize - 1;
}
//Natural Selection
private int CalculateFitness(MapData mapData)
{
int numberOfObstacles = mapData.obstacleArray.Where(isObstacle => isObstacle).Count();
int score = mapData.path.Count*fitnessPathWeight + (int)(numberOfObstacles*fitnessPathWeight);
int cornersCount = mapData.cornersList.Count;
if(cornersCount >= fitnessCornerMin && cornersCount <= fitnessCornerMax)
{
score += cornersCount * fitnessCornerWeight;
}
else if(cornersCount>fitnessCornerMax)
{
score -= fitnessCornerWeight * (cornersCount - fitnessCornerMax);
}
else if(cornersCount < fitnessCornerMin)
{
score -= fitnessCornerWeight * fitnessCornerMin;
}
score -= mapData.cornersNearEachOther * fitnessNearCornerWeight;
return score;
}
private void InstantiateEnemy()
{
Instantiate(enemyPrefab, startPosition + new Vector3(.5f,.7f,.5f), Quaternion.identity);
}
public Vector3 EnemyDestination()
{
Vector3 destination = exitPosition;
return destination;
}
}
In it I have the EnemyDestination () method:
public Vector3 EnemyDestination()
{
Vector3 destination = exitPosition;
return destination;
}
It returns to me the destination where the GameObject should go, but the exitPosition variable will only be set up as soon as I except the RunAlgorithm () method:
public void RunAlgorithm()
{
UiController.instance.ResetScreen();
UiController.instance.HideStartButton();
UiController.instance.showLevelButton();
ResetAlgorithmVariables();
mapVisualizer.ClearMap();
grid = new MapGrid(widthOfMap, lengthOfMap);
MapHelper.RandomlyChooseAndSetStartAndExit(grid, ref startPosition, ref exitPosition, randomStartAndEnd, startPositionEdge, exitPositionEdge);
isAlgorithmRunning = true;
startDate = DateTime.Now;
FindOptimalSolution(grid);
Debug.Log(EnemyDestination());
InvokeRepeating("InstantiateEnemy", 5f, 5f);
}
But now I have the Enemy.cs Script:
public class Enemy : MonoBehaviour
{
private MapBrain brain;
public float speed = 5f;
void Awake()
{
brain = GetComponent<MapBrain>();
}
void Update()
{
while (Vector3.Distance(transform.position, brain.EnemyDestination()) > 0.02f)
{
transform.position = Vector3.Lerp(transform.position, brain.EnemyDestination(), speed * Time.deltaTime);
}
}
void OnCollisionEnter(Collision other)
{
if(other.gameObject.CompareTag("Tower"))
{
Destroy(gameObject);
}
}
}
In it I'm trying to get the enemy to go to exitPosition, referencing the EnemyDestination () method, but I'm not getting it, does anyone know how I could do this?
Answer by IKDev · Aug 24, 2020 at 07:50 PM
Try using Vector2.MoveTowards() or Vector2.SmoothDamp()
I forgot to mark as solved. I did it this way:
First I put a Nav$$anonymous$$eshAgent in my $$anonymous$$apBrain script, then I made the following code for my InstantiateEnemy () method:
private void InstantiateEnemy()
{
enemyPrefab = (GameObject) Instantiate(enemyPrefab, startPosition + new Vector3(.5f,.7f,.5f), Quaternion.identity);
nav$$anonymous$$eshAgent = enemyPrefab.GetComponent<Nav$$anonymous$$eshAgent>();
if(enemyPrefab.transform.position != exitPosition)
{
nav$$anonymous$$eshAgent.SetDestination(exitPosition);
}
}
So he recognizes the path that has to go and where it has to go, and my Enemy.cs script just got a lot simpler:
public class Enemy : $$anonymous$$onoBehaviour
{
private Rigidbody enemyRb;
void Start()
{
enemyRb = GetComponent<Rigidbody>();
}
void OnCollisionEnter(Collision other)
{
if(other.gameObject.CompareTag("Tower"))
{
Destroy(gameObject);
}
}
}
Your answer
Follow this Question
Related Questions
Using Raycast hit to set vector position then moving player to that position 2 Answers
Helicopter Move Local Position,Local Position 1 Answer
how to transform player movement in side right and left like a temple run or subway surfer 0 Answers
How to play animation depending on distance ?? (Video) 0 Answers
Move a object along a vector 1 Answer