So, I guess time has come to me ask my first question on the forum, since chatGPT unable to help me.
I making a game were a car moves forward and player can rotate a turret on that car to shoot zombies. So, I make a three ground segments, each with their own NavMeshSurface component and as car moves forward, first segments changes position to the last and so on (so they are recycling).
I also have a spawner for enemies, that should place them in a specified distance from current car position. But he places them on the edge of the current ground segment instead.
Here`s the spawner code:
public class EnemySpawner : MonoBehaviour
{
[SerializeField] private float _spawnRate = 1.4f;
[SerializeField] private float _spawnDistance = 75f; // Distance from player when spawn
[SerializeField] private float _spawnRangeX = 25f; // Range for random X position when spawn
[SerializeField] private ObjectPool _enemies;
private int _spawnCount = 0;
private int _maxSpawnCount = 25;
private void Start()
{
_enemies.ObjectReturnedEvent += OnReturnedToPool;
StartCoroutine(SpawnCoroutine());
}
private void OnDestroy()
{
_enemies.ObjectReturnedEvent -= OnReturnedToPool;
}
private IEnumerator SpawnCoroutine()
{
while (true)
{
SpawnEnemy();
yield return new WaitForSeconds(_spawnRate);
}
}
private void SpawnEnemy()
{
Enemy enemy = _enemies.GetObject().GetComponent<Enemy>();
enemy.SetPool(_enemies);
Vector3 spawnPoint = GameManager.Instance.Player.transform.position;
spawnPoint += Vector3.forward * _spawnDistance;
spawnPoint += Vector3.left * Random.Range(-_spawnRangeX, _spawnRangeX);
enemy.transform.position = spawnPoint;
Debug.Log($"Spawn Point: {spawnPoint} --- Enemy Position: {enemy.transform.position}");
_spawnCount++;
}
private void OnReturnedToPool()
{
_spawnCount--;
}
}
As far as I understand, problem somehow in the NavMesh but I’m run out of ideas how to fix that. Or maybe I make easy things 1000 times harder, how I always do. However, if someone could enlighten me in that matter I be grateful for the end of time.
There is also code for my recycling ground segments:
public class GroundSpawner : MonoBehaviour
{
public GroundSpawner Instance;
[SerializeField] private int _levelLength = 3;
private float _groundOffset = -105f;
private int _segmentsPassed = 0;
[SerializeField] GameObject[] _groundSegments;
private GameObject _nextSegment;
public GameObject NextSegment => _nextSegment;
private void Awake()
{
Instance = this;
}
private void Start()
{
_groundOffset = _groundSegments[0].GetComponentInChildren<MeshRenderer>().bounds.size.z;
foreach (var segment in _groundSegments)
{
segment.GetComponent<GroundSegment>().FinishedSegmentEvent += OnSegmentPassed;
}
}
private void OnDestroy()
{
foreach (var segment in _groundSegments)
{
segment.GetComponent<GroundSegment>().FinishedSegmentEvent -= OnSegmentPassed;
}
}
private void OnSegmentPassed()
{
_segmentsPassed++;
MoveSegment();
}
private void MoveSegment()
{
GameObject firstSegment = _groundSegments[0];
firstSegment.transform.position += Vector3.forward * _groundOffset * _groundSegments.Length;
for (int i = 0; i < _groundSegments.Length - 1; i++)
{
_groundSegments[i] = _groundSegments[i + 1];
}
_groundSegments[_groundSegments.Length - 1] = firstSegment;
}
}
I have added some logs, and discovered that position is correct on spawn (in spawner and in enemy start method), but with first update of the enemy it’s position is shifted.
Also, the NavMesh Surfeces is not connected and enemies spawns across this edge of ground segment:
