Skip to main content
Post Undeleted by gjh33
deleted 310 characters in body
Source Link
gjh33
  • 691
  • 4
  • 6

A common setup for this scenarioIt is HIGHLY inadvisable to separate completely your physics logic from your damage logicmutate a collider during runtime. Start by adding 2 CollidersThis will lead to your charactermany many bugs and weird physics artifacts. One Collider will be forNot to mention it puts strain on the physics system, and will remain inas a default state. The other Collider will be called your HurtBoxlot of the broad phase and will havenarrow phase cullings can rely on the isTrigger box checked. The triggershape of the collider being cached. Changing the shape will not react withrequire the physics, but will throw a "OnTriggerEnter", "OnTriggerStay" system to re evaluate these entries. My recommendation is to have two colliders that you toggle between. Simple disable your standing collider, and "OnTriggerExit" call on whichever objectenable your rigidbody is onrolling collider. The structure I would recommend isHowever we can go further to increase the safety of what you're trying to do. Imagine the following setup:

PlayerGameObject
  {} PlayerController.cs
   -Character [Rigidbody,CollidersGameObject
     - StandingBodyColliderGameObject - Layer: "Default"
       {} Collider, 
 Controller, Health]   - RollingBodyColliderGameObject - Layer: "Default"
       {} Collider (Rolling) // Disabled
   -HurtBox [Trigger,RollUnderColliderGameObject HurtBox]- Layer: "Roll Under"
     {} Collider (Same as standing but only collides with Roll Under)

RigidbodyThe idea here is you have your standing and rolling hitboxes for physical interactions with other things in the rigidbody ofgame. However in your charactercollision matrix, Collider ismake it so the "Roll Under" layer only collides with itself. This means your normal collider that will react to physics mentioned above. Controller is responsible AND ONLY responsible for handling movementpass through and character state. It should handle your "Dodge Roll"surfaces you could roll under. Health is a script responsible AND ONLY responsible for handlingHowever if you have your current health. This includes receiving damage. Now in the child gameobjectRollUnderCollider enabled, Trigger is the trigger thatit will collide with things that can damage yourthose surfaces and stop the player. You may wish to extend this model from being able to have several hurt boxes, itmove through. When you want damage to be more precise onroll, simply disable this collider. This will let your character phase through. Or this can be as simple as a capsule trigger that matchesIf you want your physics Colliderplayer's standard hitbox to also shrink, disable the standing body collider and enable rolling body collider. Your HurtBoxHowever this rolling body collider will have your OnTriggerEnter functionstill phase through the roll under. This function will work on the same object asmeans that if your collider OR onsurface is slightly slanted, or not the object ofexact right height, your rigidbodyroll will still work. But we'll put it on the childWhen your roll is over, check if there's a roll under object justabove you (you can use physics queries for organizationthis). The HurtBox script will decide what hits itIf not, and will tellrestore your Health script to receive a certain amount of damageRollUnderCollider. For example

public Health AffectedHealth; // Set in editor

private void OnTriggerEnter(Collider otherCollider)
{
  EnemyBullet bullet = otherCollider.GetComponent<EnemyBullet>();
  if (bullet != null) {
    AffectedHealth.Damage(bullet.DamageAmount);
  }
}

Your Health script as you can seeAgain, will have a Damage function. Your Health script should also have a function called "MakeInvulnerable" and "MakeVulnerable". The final idea herethe reason for this multi collider setup is that your Controllerphysics performance, calls MakeInvulnerable on your health script when you rolledge case safety, and MakeVulnerable when the roll is doneless constraint on level design. Your hurtbox is constantly enabled and sending any damage requestsWhat you're trying to Healthdo isn't an easy problem, but Health itself is blocking it. Some cool things about this isand an easy solution will likely turn complex very quickly as you could use this information to track stats, like damage mitigated, damage taken, etcgo through edge cases. Since HealthThis is always receiving the damage function calls. You can also optimize this method by usingjust my recommendation from time in the collision matrixindustry and putting your hurtbox on it's own layer, so only certain collisions will registerdealing with itchanging colliders.

A common setup for this scenario is to separate completely your physics logic from your damage logic. Start by adding 2 Colliders to your character. One Collider will be for physics, and will remain in a default state. The other Collider will be called your HurtBox and will have the isTrigger box checked. The trigger collider will not react with physics, but will throw a "OnTriggerEnter", "OnTriggerStay", and "OnTriggerExit" call on whichever object your rigidbody is on. The structure I would recommend is the following

-Character [Rigidbody, Collider, Controller, Health]
  -HurtBox [Trigger, HurtBox]

Rigidbody is the rigidbody of your character, Collider is the collider that will react to physics mentioned above. Controller is responsible AND ONLY responsible for handling movement and character state. It should handle your "Dodge Roll". Health is a script responsible AND ONLY responsible for handling your current health. This includes receiving damage. Now in the child gameobject, Trigger is the trigger that will collide with things that can damage your player. You may wish to extend this model to have several hurt boxes, it you want damage to be more precise on your character. Or this can be as simple as a capsule trigger that matches your physics Collider. Your HurtBox will have your OnTriggerEnter function. This function will work on the same object as your collider OR on the object of your rigidbody. But we'll put it on the child object just for organization. The HurtBox script will decide what hits it, and will tell your Health script to receive a certain amount of damage. For example

public Health AffectedHealth; // Set in editor

private void OnTriggerEnter(Collider otherCollider)
{
  EnemyBullet bullet = otherCollider.GetComponent<EnemyBullet>();
  if (bullet != null) {
    AffectedHealth.Damage(bullet.DamageAmount);
  }
}

Your Health script as you can see, will have a Damage function. Your Health script should also have a function called "MakeInvulnerable" and "MakeVulnerable". The final idea here is that your Controller, calls MakeInvulnerable on your health script when you roll, and MakeVulnerable when the roll is done. Your hurtbox is constantly enabled and sending any damage requests to Health, but Health itself is blocking it. Some cool things about this is you could use this information to track stats, like damage mitigated, damage taken, etc. Since Health is always receiving the damage function calls. You can also optimize this method by using the collision matrix and putting your hurtbox on it's own layer, so only certain collisions will register with it.

It is HIGHLY inadvisable to mutate a collider during runtime. This will lead to many many bugs and weird physics artifacts. Not to mention it puts strain on the physics system, as a lot of the broad phase and narrow phase cullings can rely on the shape of the collider being cached. Changing the shape will require the physics system to re evaluate these entries. My recommendation is to have two colliders that you toggle between. Simple disable your standing collider, and enable your rolling collider. However we can go further to increase the safety of what you're trying to do. Imagine the following setup:

PlayerGameObject
  {} PlayerController.cs
   - CollidersGameObject
     - StandingBodyColliderGameObject - Layer: "Default"
       {} Collider 
     - RollingBodyColliderGameObject - Layer: "Default"
       {} Collider (Rolling) // Disabled
   - RollUnderColliderGameObject - Layer: "Roll Under"
     {} Collider (Same as standing but only collides with Roll Under)

The idea here is you have your standing and rolling hitboxes for physical interactions with other things in the game. However in your collision matrix, make it so the "Roll Under" layer only collides with itself. This means your normal collider will pass through and surfaces you could roll under. However if you have your RollUnderCollider enabled, it will collide with those surfaces and stop the player from being able to move through. When you roll, simply disable this collider. This will let your character phase through. If you want your player's standard hitbox to also shrink, disable the standing body collider and enable rolling body collider. However this rolling body collider will still phase through the roll under. This means that if your surface is slightly slanted, or not the exact right height, your roll will still work. When your roll is over, check if there's a roll under object above you (you can use physics queries for this). If not, restore your RollUnderCollider. Again, the reason for this multi collider setup is physics performance, edge case safety, and less constraint on level design. What you're trying to do isn't an easy problem, and an easy solution will likely turn complex very quickly as you go through edge cases. This is just my recommendation from time in the industry and dealing with changing colliders.

Post Deleted by gjh33
Source Link
gjh33
  • 691
  • 4
  • 6

A common setup for this scenario is to separate completely your physics logic from your damage logic. Start by adding 2 Colliders to your character. One Collider will be for physics, and will remain in a default state. The other Collider will be called your HurtBox and will have the isTrigger box checked. The trigger collider will not react with physics, but will throw a "OnTriggerEnter", "OnTriggerStay", and "OnTriggerExit" call on whichever object your rigidbody is on. The structure I would recommend is the following

-Character [Rigidbody, Collider, Controller, Health]
  -HurtBox [Trigger, HurtBox]

Rigidbody is the rigidbody of your character, Collider is the collider that will react to physics mentioned above. Controller is responsible AND ONLY responsible for handling movement and character state. It should handle your "Dodge Roll". Health is a script responsible AND ONLY responsible for handling your current health. This includes receiving damage. Now in the child gameobject, Trigger is the trigger that will collide with things that can damage your player. You may wish to extend this model to have several hurt boxes, it you want damage to be more precise on your character. Or this can be as simple as a capsule trigger that matches your physics Collider. Your HurtBox will have your OnTriggerEnter function. This function will work on the same object as your collider OR on the object of your rigidbody. But we'll put it on the child object just for organization. The HurtBox script will decide what hits it, and will tell your Health script to receive a certain amount of damage. For example

public Health AffectedHealth; // Set in editor

private void OnTriggerEnter(Collider otherCollider)
{
  EnemyBullet bullet = otherCollider.GetComponent<EnemyBullet>();
  if (bullet != null) {
    AffectedHealth.Damage(bullet.DamageAmount);
  }
}

Your Health script as you can see, will have a Damage function. Your Health script should also have a function called "MakeInvulnerable" and "MakeVulnerable". The final idea here is that your Controller, calls MakeInvulnerable on your health script when you roll, and MakeVulnerable when the roll is done. Your hurtbox is constantly enabled and sending any damage requests to Health, but Health itself is blocking it. Some cool things about this is you could use this information to track stats, like damage mitigated, damage taken, etc. Since Health is always receiving the damage function calls. You can also optimize this method by using the collision matrix and putting your hurtbox on it's own layer, so only certain collisions will register with it.