# How can I avoid instantiating multiple instances of a RigidBody?

I could use a little help.

I've a state machine for an NPC that does a melee attack. The problem I'm running into is that the current code instantiates multiple instances when I only need one per cycle.

I could use some ideas.

This is the chunk of code I'm working with:

public void ChaseToAttack()
{
_navMeshAgent.speed = 3.5f;//slow down the navAgent

float playerDistance = Vector3.Distance(chaseTarget.position, transform.position);
//stop navMeshAgent to begin attack sequence
if (playerDistance <= stopAtDistance)
{
/// ensure enemy is always looking at player
enemyToTarget = ((chaseTarget.position + offset) - eyes.transform.position);
if(Physics.Raycast(eyes.position, enemyToTarget, out _hit, sightRange) && _hit.collider.CompareTag("Player"))
{
_navMeshAgent.Stop();
currentState = _attackState;
//StartCoroutine(FistTimer());
PunchCycle();
}
/// ensure the enemy isn't hitting air & will always look for the player
else
{
transform.Rotate(chaseTarget.position, searchTurnSpeed * Time.deltaTime, 0);
}
/// end look & atttack player block
}
}

void PunchCycle()
{
StartCoroutine(AttackCycle());
}

void PunchClone()
{
clone = Instantiate(pfbPunch, transform.position, transform.rotation) as Rigidbody;
clone.transform.Translate(0,1f,0);
clone.velocity = transform.TransformDirection(0.0f,0.0f,0.125f * punchDistance);
}

IEnumerator AttackCycle()
{
//move animation here
AnimPunch();
PunchClone();
yield return new WaitForSeconds(4f);//fistTimer

}


EDIT:

Changed the code so it would only instantiate once- but now, it will only instantiate only once even though it's still in the attack sequence.

    public void ChaseToAttack()
{
_navMeshAgent.speed = 3.5f;//slow down the navAgent

float playerDistance = Vector3.Distance(chaseTarget.position, transform.position);
//stop navMeshAgent to begin attack sequence
if (playerDistance <= stopAtDistance)
{
/// ensure enemy is always looking at player
enemyToTarget = ((chaseTarget.position + offset) - eyes.transform.position);
if(Physics.Raycast(eyes.position, enemyToTarget, out _hit, sightRange) && _hit.collider.CompareTag("Player"))
{
_navMeshAgent.Stop();
currentState = _attackState;
StartCoroutine(AttackCycle());
}
/// ensure the enemy isn't hitting air & will always look for the player
else
{
transform.Rotate(chaseTarget.position, searchTurnSpeed * Time.deltaTime, 0);
}
/// end look & atttack player block
}
}
void PunchClone()
{
if(!didClone)
{
clone = Instantiate(pfbPunch, transform.position, transform.rotation) as Rigidbody;
clone.transform.Translate(0,1f,0);
clone.velocity = transform.TransformDirection(0.0f,0.0f,0.125f * punchDistance);
}
didClone = true;
}
IEnumerator AttackCycle()
{
//move animation here
AnimPunch();
yield return new WaitForSeconds(0.75f);//fistTimer
PunchClone();
}

• I added an edit to my answer. You have to set the boolean to false again. – ElDuderino Dec 8 '15 at 9:18

So I've found a simple solution to synchronize the punch sequence without having to deal with coroutines or instantiating/destroying rigidbodies.

public void AttackCycle()
{
_navMeshAgent.Stop();
AnimPunch();
nmeFistL.SetActive(true);
if (_animation["nmePunch"].time >= 1.5f)
{
nmeFistL.SetActive(false);
}
}


I am not sure why you have to instantiate the Rigidbody, but you can just destroy them when you are done punching.

Rigidbody PunchClone()
{
clone = Instantiate(pfbPunch, transform.position, transform.rotation) as Rigidbody;
clone.transform.Translate(0,1f,0);
clone.velocity = transform.TransformDirection(0.0f,0.0f,0.125f * punchDistance);
return clone;
}

IEnumerator AttackCycle()
{
//move animation here
AnimPunch();
Rigidbody r = PunchClone();
yield return new WaitForSeconds(4f);//fistTimer
Destroy(r.gameObject);

}


Edit : If you need only one instance active at any time, then going with your boolean method is fine, but you have to set the boolean to false again. You can do that where I do the Destroy(r.gameObject).

• Thanks ElDuderino, I need to instantiate a clone to correspond with the animation sequence (It would end up hitting the player 2x if I didn't). I originally had the collider activate/deactivate but that method ended up bogging down the game. – Mark Laurel Dec 8 '15 at 2:54
• This method is still producing multiple instances. – Mark Laurel Dec 8 '15 at 3:04
• ElDuderino, I get "The name r' does not exist in the current context" when I added encapsulated - Rigidbody r = PunchClone(); - inside (!didClone) – Mark Laurel Dec 9 '15 at 1:07

void PunchClone() { if(!didClone) { clone = Instantiate(pfbPunch, transform.position, transform.rotation) as Rigidbody; clone.transform.Translate(0,1f,0); clone.velocity = transform.TransformDirection(0.0f,0.0f,0.125f * punchDistance); } didClone = true; }

There, didClone=true should be inside the if(!didClone){} block. After the if block, add

else didClone=false;`

This will ensure that next time the method is called, the value of didClone will be toggled.

• Thanks SanSolo, I've gone this route & it also creates multiple clones... – Mark Laurel Dec 8 '15 at 20:59