Basis festgelegt
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class CharacterRotation : MonoBehaviour
|
||||
{
|
||||
[Header("Visual")]
|
||||
[SerializeField]
|
||||
private Transform visual;
|
||||
|
||||
[Header("Rotation")]
|
||||
[SerializeField]
|
||||
private float rotationSpeed = 540f;
|
||||
|
||||
[Tooltip("In welche lokale Richtung zeigt die Grafik standardm??ig?")]
|
||||
[SerializeField]
|
||||
private SpriteForwardDirection spriteForward =
|
||||
SpriteForwardDirection.Up;
|
||||
|
||||
private IMovementDirection movement;
|
||||
|
||||
private enum SpriteForwardDirection
|
||||
{
|
||||
Up,
|
||||
Right
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
movement =
|
||||
GetComponent<IMovementDirection>();
|
||||
|
||||
if (movement == null)
|
||||
{
|
||||
Debug.LogError(
|
||||
"CharacterRotation ben?tigt eine Komponente, " +
|
||||
"die IMovementDirection implementiert.",
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
if (visual == null)
|
||||
{
|
||||
Debug.LogError(
|
||||
"CharacterRotation: Kein Visual zugewiesen.",
|
||||
this
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (movement == null || visual == null)
|
||||
return;
|
||||
|
||||
Vector2 direction =
|
||||
movement.MovementDirection;
|
||||
|
||||
// Keine Bewegung -> aktuelle Rotation behalten.
|
||||
if (direction.sqrMagnitude < 0.001f)
|
||||
return;
|
||||
|
||||
RotateTowards(direction);
|
||||
}
|
||||
|
||||
private void RotateTowards(Vector2 direction)
|
||||
{
|
||||
float targetAngle =
|
||||
Mathf.Atan2(
|
||||
direction.y,
|
||||
direction.x
|
||||
) * Mathf.Rad2Deg;
|
||||
|
||||
if (spriteForward ==
|
||||
SpriteForwardDirection.Up)
|
||||
{
|
||||
targetAngle -= 90f;
|
||||
}
|
||||
|
||||
Quaternion targetRotation =
|
||||
Quaternion.Euler(
|
||||
0f,
|
||||
0f,
|
||||
targetAngle
|
||||
);
|
||||
|
||||
visual.rotation =
|
||||
Quaternion.RotateTowards(
|
||||
visual.rotation,
|
||||
targetRotation,
|
||||
rotationSpeed * Time.deltaTime
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bea87a19f3a99294c9d065a24307484c
|
||||
@@ -0,0 +1,97 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class Enemy : MonoBehaviour, IMovementDirection
|
||||
{
|
||||
[Header("Movement")]
|
||||
[SerializeField]
|
||||
private float moveSpeed = 2f;
|
||||
|
||||
[SerializeField]
|
||||
private float targetReachedDistance = 0.1f;
|
||||
|
||||
private EnemyTargetManager targetManager;
|
||||
private Transform currentTarget;
|
||||
|
||||
// Wird von CharacterRotation verwendet.
|
||||
public Vector2 MovementDirection { get; private set; }
|
||||
|
||||
private void Start()
|
||||
{
|
||||
targetManager = FindFirstObjectByType<EnemyTargetManager>();
|
||||
|
||||
if (targetManager == null)
|
||||
{
|
||||
Debug.LogError(
|
||||
"Enemy: Kein EnemyTargetManager gefunden!",
|
||||
this
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SelectClosestTarget();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (targetManager == null)
|
||||
return;
|
||||
|
||||
if (currentTarget == null)
|
||||
{
|
||||
MovementDirection = Vector2.zero;
|
||||
SelectClosestTarget();
|
||||
return;
|
||||
}
|
||||
|
||||
// Falls das Ziel deaktiviert wurde:
|
||||
if (!currentTarget.gameObject.activeInHierarchy)
|
||||
{
|
||||
SelectClosestTarget();
|
||||
return;
|
||||
}
|
||||
|
||||
MoveTowardsTarget();
|
||||
|
||||
if (HasReachedTarget())
|
||||
{
|
||||
SelectClosestTarget();
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectClosestTarget()
|
||||
{
|
||||
currentTarget =
|
||||
targetManager.GetClosestActiveTarget(transform.position);
|
||||
|
||||
if (currentTarget == null)
|
||||
{
|
||||
MovementDirection = Vector2.zero;
|
||||
}
|
||||
}
|
||||
|
||||
private void MoveTowardsTarget()
|
||||
{
|
||||
Vector3 direction =
|
||||
currentTarget.position - transform.position;
|
||||
|
||||
MovementDirection = new Vector2(
|
||||
direction.x,
|
||||
direction.y
|
||||
).normalized;
|
||||
|
||||
transform.position = Vector3.MoveTowards(
|
||||
transform.position,
|
||||
currentTarget.position,
|
||||
moveSpeed * Time.deltaTime
|
||||
);
|
||||
}
|
||||
|
||||
private bool HasReachedTarget()
|
||||
{
|
||||
return Vector3.Distance(
|
||||
transform.position,
|
||||
currentTarget.position
|
||||
) <= targetReachedDistance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 544fe3d5f687b6b4bbe68d79ffb11bd8
|
||||
@@ -0,0 +1,68 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
public class EnemySpawner : MonoBehaviour
|
||||
{
|
||||
[Header("Enemy")]
|
||||
[SerializeField]
|
||||
private GameObject enemyPrefab;
|
||||
|
||||
[Header("Spawn")]
|
||||
[SerializeField]
|
||||
private Transform spawnPoint;
|
||||
|
||||
[SerializeField]
|
||||
private float minSpawnDelay = 0.5f;
|
||||
|
||||
[SerializeField]
|
||||
private float maxSpawnDelay = 2f;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (enemyPrefab == null)
|
||||
{
|
||||
Debug.LogError(
|
||||
"EnemySpawner: Kein Enemy-Prefab zugewiesen!",
|
||||
this
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (spawnPoint == null)
|
||||
{
|
||||
Debug.LogError(
|
||||
"EnemySpawner: Kein SpawnPoint zugewiesen!",
|
||||
this
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
StartCoroutine(SpawnLoop());
|
||||
}
|
||||
|
||||
private IEnumerator SpawnLoop()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
float delay = Random.Range(
|
||||
minSpawnDelay,
|
||||
maxSpawnDelay
|
||||
);
|
||||
|
||||
yield return new WaitForSeconds(delay);
|
||||
|
||||
SpawnEnemy();
|
||||
}
|
||||
}
|
||||
|
||||
private void SpawnEnemy()
|
||||
{
|
||||
Instantiate(
|
||||
enemyPrefab,
|
||||
spawnPoint.position,
|
||||
spawnPoint.rotation
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eed070947de809f4d9fd7c87e1d9b1c3
|
||||
@@ -0,0 +1,49 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class EnemyTargetManager : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private List<Transform> targetPoints = new List<Transform>();
|
||||
|
||||
public Transform GetClosestActiveTarget(Vector3 position)
|
||||
{
|
||||
List<Transform> closestTargets =
|
||||
new List<Transform>();
|
||||
|
||||
float closestDistanceSqr = float.MaxValue;
|
||||
|
||||
foreach (Transform target in targetPoints)
|
||||
{
|
||||
if (target == null || !target.gameObject.activeInHierarchy)
|
||||
continue;
|
||||
|
||||
float distanceSqr =
|
||||
(target.position - position).sqrMagnitude;
|
||||
|
||||
if (distanceSqr < closestDistanceSqr)
|
||||
{
|
||||
closestDistanceSqr = distanceSqr;
|
||||
|
||||
closestTargets.Clear();
|
||||
closestTargets.Add(target);
|
||||
}
|
||||
else if (Mathf.Approximately(
|
||||
distanceSqr,
|
||||
closestDistanceSqr))
|
||||
{
|
||||
closestTargets.Add(target);
|
||||
}
|
||||
}
|
||||
|
||||
if (closestTargets.Count == 0)
|
||||
return null;
|
||||
|
||||
int randomIndex = Random.Range(
|
||||
0,
|
||||
closestTargets.Count
|
||||
);
|
||||
|
||||
return closestTargets[randomIndex];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6ac3932d87de0d64180930ddb4e2f576
|
||||
@@ -0,0 +1,6 @@
|
||||
using UnityEngine;
|
||||
|
||||
public interface IMovementDirection
|
||||
{
|
||||
Vector2 MovementDirection { get; }
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 649a0945a4204564187826046e548805
|
||||
Reference in New Issue
Block a user