Hi,
I want the units (workers) go to the nearest resources, wait there till 5 seconds, then return to nearest resourcebox. For this, I used the switch statement like this:
private void Start()
{
AllObjects = GameObject.FindGameObjectsWithTag("OBJ");
resourceBox = GameObject.FindGameObjectsWithTag("ResourceBox");
}
private void Awake()
{
state = State.Idle;
}
private void Update()
{
switch (state)
{
case State.Idle:
state = State.MovingToResource;
break;
case State.MovingToResource:
float step = speed * Time.deltaTime;
for (int i = 0; i < AllObjects.Length; i++)
{
distance = Vector3.Distance(this.transform.position, AllObjects[i].transform.position);
if (distance < nearestDistance)
{
nearestOBJ = AllObjects[i];
nearestDistance = distance;
transform.position = Vector3.MoveTowards(transform.position, AllObjects[i].transform.position, step);
state = State.GatheringResource;
}
}
break;
case State.GatheringResource:
timer -= Time.deltaTime;
if (timer <= 0)
{
state = State.MovingToStorage;
}
break;
case State.MovingToStorage:
float stepR = speed * Time.deltaTime;
for (int i = 0; i < resourceBox.Length; i++)
{
distance_R = Vector3.Distance(this.transform.position, resourceBox[i].transform.position);
if (distance_R < nearestDistance_R)
{
nearestOBJ = resourceBox[i];
nearestDistance_R = distance_R;
transform.position = Vector3.MoveTowards(transform.position, resourceBox[i].transform.position, stepR);
goldInventoryAmount = 0;
state = State.Idle;
}
}
break;
}
}
}
Though I’ve defined the timer at State.GatheringResource: , at start, the workers wait for 5 seconds before they head to resources and stay put at the resources.
I am a bit concerned not so much about the five-second issue but rather want to clarify overall whether your code is currently functioning correctly, and if workers indeed go to resources and back?
Because judging by the code of several cases, for example, this one
case State.MovingToResource:
float step = speed * Time.deltaTime;
for (int i = 0; i < AllObjects.Length; i++)
{
distance = Vector3.Distance(this.transform.position, AllObjects[i].transform.position);
if (distance < nearestDistance)
{
nearestOBJ = AllObjects[i];
nearestDistance = distance;
transform.position = Vector3.MoveTowards(transform.position, AllObjects[i].transform.position, step);
state = State.GatheringResource;
}
}
break;
or that one
case State.MovingToStorage:
float stepR = speed * Time.deltaTime;
for (int i = 0; i < resourceBox.Length; i++)
{
distance_R = Vector3.Distance(this.transform.position, resourceBox[i].transform.position);
if (distance_R < nearestDistance_R)
{
nearestOBJ = resourceBox[i];
nearestDistance_R = distance_R;
transform.position = Vector3.MoveTowards(transform.position, resourceBox[i].transform.position, stepR);
goldInventoryAmount = 0;
state = State.Idle;
}
}
break;
it seems that the worker iterates through all resources and takes a step towards the one that is closer within a certain distance. HOWEVER, in principle, each resource from the list could be closer than a certain distance, and the worker would take a step towards one resource first, then towards another resource, i.e., moving back and forth. Moreover, I see that after the first step, another case immediately follows. So, the implementation of the worker’s movements is somewhat unclear… Well, never mind.
I see that your problem is still unresolved; you created a similar topic a little while ago. Perhaps my previous response deterred you, so I’ll try to refine the idea behind your code a bit.
In fact, this approach is not very flexible, but based on using a switch statement, it might look something like this:
using UnityEngine;
public class Unitkiv : MonoBehaviour
{
public float nearestDistance = 5f;
public float speed = 1f;
public float gatheringTime = 2f;
private Transform nearestResource;
private Transform nearestStorage;
private float gatheringElapsedTimer;
private State state;
enum State
{
Idle,
MovingToResource,
GatheringResource,
MovingToStorage
}
private void Awake()
{
state = State.Idle;
}
private void Update()
{
switch (state)
{
case State.Idle:
nearestResource = FindNearestResource();
if (nearestResource != null)
{
state = State.MovingToResource;
}
else
{
Debug.Log("No nearby resources were found.");
}
break;
case State.MovingToResource:
bool hasReachedResource = MoveTo(nearestResource);
if (hasReachedResource)
{
nearestResource = null;
gatheringElapsedTimer = 0;
state = State.GatheringResource;
}
break;
case State.GatheringResource:
gatheringElapsedTimer += Time.deltaTime;
if (gatheringElapsedTimer >= gatheringTime)
{
nearestStorage = FindNearestStorage();
if (nearestStorage != null)
{
state = State.MovingToStorage;
}
else
{
Debug.Log("No nearby storages were found.");
}
}
break;
case State.MovingToStorage:
bool hasReachedStorage = MoveTo(nearestStorage);
if (hasReachedStorage)
{
nearestStorage = null;
state = State.Idle;
}
break;
}
}
private Transform FindNearestResource() => FindNearestByTag("ResourceBox");
private Transform FindNearestStorage() => FindNearestByTag("OBJ");
// Select the closest target among those that can be reached.
private Transform FindNearestByTag(string tag)
{
float minDist = float.MaxValue;
Transform nearestTransform = null;
foreach (GameObject resource in GameObject.FindGameObjectsWithTag(tag))
{
float dist = (resource.transform.position - transform.position).sqrMagnitude;
if (dist < nearestDistance * nearestDistance && dist < minDist)
{
minDist = dist;
nearestTransform = resource.transform;
}
}
return nearestTransform;
}
// Move towards the target. Returns true if reached the target and false if not yet reached.
private bool MoveTo(Transform target)
{
transform.position = Vector3.MoveTowards(transform.position, target.position, speed * Time.deltaTime);
return (transform.position - target.position).sqrMagnitude == 0;
}
}
1 Like
I would examine your code… Thank you for your time and thanks a lot:)
1 Like
I want it to popup with a text that says how many resources left as the worker return to Storage. For this, made a script which holds the resource (I used the Codemonkey’s Utility for popping up the text as the worker return on the way) :
using CodeMonkey;
public class ResourceNode
{
private Transform resourceNodeTransform;
private int resourceAmount;
public ResourceNode(Transform resourceNodeTransform)
{
this.resourceNodeTransform = resourceNodeTransform;
resourceAmount = 3;
}
public Vector3 GetPosition()
{
return resourceNodeTransform.position;
}
public void GrabResource()
{
resourceAmount -= 1;
CMDebug.TextPopupMouse("resourceAmount: " + resourceAmount);
}
public bool HasResource()
{
return resourceAmount > 0;
}
}
And in the UnitMove script I’ve changed the script like this:
case State.MovingToResource:
bool hasReachedResource = MoveTo(nearestResource);
if (hasReachedResource)
{
gatheringElapsedTimer = 0;
state = State.GatheringResource;
// the changes that is made
resourceNode.GetPosition();
}
break;
case State.GatheringResource:
gatheringElapsedTimer += Time.deltaTime;
if (gatheringElapsedTimer >= gatheringTime)
{
nearestStorage = FindNearestStorage();
if (nearestStorage != null)
{
state = State.MovingToStorage;
// the changes that is made
resourceNode.GetPosition();
resourceNode.GrabResource();
}
else
{
Debug.Log("No nearby storages were found.");
}
}
break;
But the text won’t popup.
Your calls to the GetPosition() method on lines 11 and 28 are entirely nonsensical. This method simply returns a Vector3, yet you don’t store its value anywhere. Additionally, the rationale behind calling this method is unclear, and it’s unclear what you expected to achieve.
As for displaying the popup window using CMDebug.TextPopupMouse, I’m unable to provide guidance as I’m not familiar with its operational nuances. It’s possible that some preliminary setup may be required.
1 Like