So I'm using Astar pathfinding project plugin and I have a target
Transform, which is a point where the AI builds its path.
Currently I'm trying to implement a roaming state to my enemy. I've decided to create a random point and just shove it to target
, but every solution I know or I've found regarding creating a random point is in either Vector2
or Vector3
.
How to create a random point and reference it to Transform variable?
I've tried this solution from Astar project's tutorual (Method 1), but that didn't work for me. Here's almost the whole code just in case. The problem is in a state machine in a state Roaming.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Pathfinding;
public class EnemyAI : MonoBehaviour
{
private Transform target; //that's what's all the fuss about
private GameObject player;
public float speed = 200f;
public float nextWaypointDistance = 3f;
public float radius;
private float repeatPath = .5f;
enum State
{
Roaming,
ChaseTarget,
Attacking,
}
private State state;
Path path;
int currentWaypoint;
bool reachedEndOfDestination = false;
private Animator animator;
private float horizontal;
private float vertical;
private Vector2 force;
private GameObject gfx;
private bool setAttackTimer;
private float attackTimer;
Seeker seeker;
Rigidbody2D rb;
private void Awake()
{
//state = State.Roaming;
}
void Start()
{
seeker = GetComponent<Seeker>();
rb = GetComponent<Rigidbody2D>();
gfx = GameObject.Find("CQBgfx");
animator = gfx.GetComponent<Animator>();
player = GameObject.Find("Player");
target = player.transform;
state = State.ChaseTarget;
InvokeRepeating("UpdatePath", 0f, repeatPath);
}
void UpdatePath()
{
if (seeker.IsDone())
seeker.StartPath(rb.position, target.position, OnPathComplete); //Here's the plugin forces me to use Transform
}
void OnPathComplete(Path p)
{
if (!p.error)
{
path = p;
currentWaypoint = 1;
reachedEndOfDestination = false;
}
}
void FixedUpdate()
{
Movement();
MovementAnimator();
}
private void Update()
{
switch (state)
{
default:
case State.Roaming:
Vector3 PickRandomPoint () {
var point = Random.insideUnitSphere * radius;
point.y = 0;
point = transform.position;
return point;
}
target = PickRandomPoint(); //Error. Vector3 cannot be converted to Transform.
break;
case State.ChaseTarget:
target = player.transform;
break;
case State.Attacking:
break;
}
}
void Movement()
{
if (path == null)
return;
if (currentWaypoint >= path.vectorPath.Count)
{
reachedEndOfDestination = true;
rb.velocity = Vector2.zero;
force = Vector2.zero;
return;
}
else
{
reachedEndOfDestination = false;
}
if (!reachedEndOfDestination)
{
Vector2 direction = ((Vector2)path.vectorPath[currentWaypoint] - rb.position).normalized;
force = direction * speed * Time.deltaTime;
rb.AddForce(force);
}
float distance = Vector2.Distance(rb.position, path.vectorPath[currentWaypoint]);
if (distance < nextWaypointDistance)
currentWaypoint ;
}
}
CodePudding user response:
If you absolutely HAVE to use a transform instance, (as I'm guessing you use transform.position
to continuously follow a target) creating an empty GameObject and moving that to the target would work.
private GameObject roamTarget; // <-- new roamTarget variable
private Transform target;
private GameObject player;
//...rest of variables
void OnEnable()
{
// create roamTarget instance and reuse it for later
roamTarget = new GameObject(gameObject.name " Roam Target"); //just gives it a readable name
}
void OnDisable()
{
// destroy our roamTarget on disable so we don't pollute our scene with unused gameobjects
Destroy(roamTarget);
}
and
private void Update()
{
switch (state)
{
default:
case State.Roaming:
roamTarget.transform.position = PickRandomPoint();
target = roamTarget;
break;
//...rest of switch cases
}
//...rest of Update()
}
Just make sure to create one and move it around, instead of constantly instantiating and destroying targets,