I'm trying to make my character do a drop attack in Unity where I want to ignore the collision detection of boxCollider2D for the moment when character & an enemy collide, then undo the ignore. So far the ignore collision is working but it's not reverting back to detect. So after the first successful drop attack my character can pass through the enemy instead of colliding. Here's my code below,
private Rigidbody2D rb;
private Animator anm;
private Collider2D coll;
private enum State {idle, running, jumping, attacking, falling, hurt}
private void OnCollisionEnter2D(Collision2D other) {
if (other.gameObject.tag == "Enemy") {
Enemy enemy = other.gameObject.GetComponent<Enemy>();
if (state == State.falling && anm.GetBool("dropAtk")) { // hurt enemy if drop attack
enemy.Hurt();
Physics2D.IgnoreCollision(other.gameObject.GetComponent<Collider2D>(), GetComponent<Collider2D>(), true);
} else { // take damange
if (other.gameObject.transform.position.x > transform.position.x) {
PlayerHurt("right");
} else {
PlayerHurt("left");
}
}
}
}
private void OnCollisionExit2D(Collision2D other) {
if (other.gameObject.tag == "Enemy") {
if (coll.IsTouchingLayers(ground)) {
Physics2D.IgnoreCollision(other.gameObject.GetComponent<Collider2D>(), GetComponent<Collider2D>(), false);
}
}
}
How can I re-enable collision detection by turning off the IgnoreCollision when character hits the ground? I'm a novice in unity so any suggestion will be really helpful. Thank you!
hope you get the idea
// Update is called once per frame
void FixedUpdate()
{
if(state==dropattck)
{
ChangeTrigger(player, true);
if(player.transform.position.y<floorvalue/*check your floor value*/)
{
transform.position.y = floorvalue;
}
}else
{
ChangeTrigger(player, false);
}
}
public void ChangeTrigger(GameObject obj,bool tf)
{
if(obj.GetComponent<Collider2D>().isTrigger!=tf)
obj.GetComponent<Collider2D>().isTrigger = tf;
}
a solution that comes to mind is to bound the position on the y axis and then temporarily set your collider to trigger. you bound the y so the player doesn't fall through the floor
otherwise you can check when your animation ends and set the collider back to detecting
Related
so here is the scenario,
i want the player to be able to perform a trick, and then be able to hold the trick for a longer duration if they want to, but if they don't hold the input then they instead just continue the animation until completion as i haven't actually tried implementing too much and its not giving me the desired result i figured i'd just ask if people have already done it so i don't spend the next 2 hours down a rabbit hole, any and all help is appreciated thanks! :D
(Unity Script)
{
[Header("Trick Attributes")]
public string GroundTagName; // Tag used for all the platforms
public KeyCode stuntKey;
public float AnimationFreezeTime = 0.75f;
public SpriteAnimator anim; // Put the Sprite animator here
public Animator spriteAnimator; // Put the Animator here
private bool isGrounded;
public bool stunting = false;
private void Start()
{
}
private void Update()
{
if (Input.GetKeyDown(stuntKey) && !isGrounded)
{
anim.StartAnimation("FlyingSquirrel");
stunting = true;
Invoke("FreezeAnimation", AnimationFreezeTime);
}
if (Input.GetKeyUp(stuntKey))
{
stunting = false;
spriteAnimator.speed = 1;
}
}
void FreezeAnimation() {
spriteAnimator.speed = 0;
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.tag == GroundTagName)
{
isGrounded = true;
}
else
{
isGrounded = false;
}
if (stunting && collision.gameObject.tag == GroundTagName)
{
Destroy(gameObject);
}
}
private void OnCollisionExit(Collision collision)
{
isGrounded = false;
}
}
FlyingSquirrel needs to be broken up into 3 different animations. This can be done in Maya, Blender, uMotion, or even Unity's animation importer:
You need 3 Animator states:
Start_FlyingSquirrel // Player moves into position
Idle_FlyingSquirrel // Player is "holding" the trick
End_FlyingSquirrel // Player let go, return to normal
When the player presses button to start the trick, play the Start animation. For the transition, use "has exit time" to proceed to the Idle State. The Idle state will be true (use a boolean Animator parameter) while the trick is "held". Uncheck "has exit time" for the transition to the End state- you want this to happen instantly.
Anyone can help me how to fix this problem i'm having?
*1st script:
public static bool attacking;
public Collider2D attackTrigger;
private void Awake()
{
attackTrigger.enabled = false;
}
private void Update()
{
if (attacking == true)
{
Debug.Log("Box Collider Enabled");
attackTrigger.enabled = true;
StartCoroutine(DisableCollider());
}
}
IEnumerator DisableCollider()
{
yield return new WaitForSeconds(1);
attacking = false;
attackTrigger.enabled = false;
Debug.Log("Box Collider Disabled");
}
*2nd script:
public float damage = .10f;
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.isTrigger!=true && collision.CompareTag("Enemy"))
{
Debug.Log("Enemy is Damaged");
EHealthBar.TakeDamage(damage);
}
}
i'm trying to get my player character to attack an enemy using collision, well it does work and the player does damage the enemy but it will only work if the enemy's box collider enters my attack again.
if the enemy is already in my area of attack which has a box collision 2d attached, the enemy doesn't get damaged and that's not what i was going for.
I can change it to OnTriggerStay2D but the enemy will keep on getting damaged till the collider is disabled again. care to help?
I think the problem is
IEnumerator DisableCollider()
{
yield return new WaitForSeconds(1);
attacking = false;
...
which causes that your IF statement in your update is still occuring for 1 second and starting a lot of coroutines. The easiest solution would be moving attacking = false; before yield, but i guess you want to use that variable to be aware if user is in attack state. So i suggest to use another bool variable.
if (invokeAttack)
{
attacking = true;
invokeAttack = false
Debug.Log("Box Collider Enabled");
attackTrigger.enabled = true;
StartCoroutine(DisableCollider());
}
Anyway, you didn't show us how you invoke attack, but maybe instead of changing variable (attacking/invokeAttack in your case) to true and checking it in Update you just invoke a method which enables collider and starts coroutine?
So here it is, Iam making a game for my thesis. The game is called hacky sack, Iam having a problem when my trigger is true because the collision for my character and the object is passing through and if idon`t have a trigger it was just basically hitting it even when my Player is running.
And can you guys help me on how the Object/Sack going up randomly when it hit. So here is my code :
public void Sipa()
{
if (canSipa == true)
{
_pitcha.GetComponent<Rigidbody2D>().AddForce(new Vector2(-400, 1000));
}
}
}
And here is for my object
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.gameObject.tag == "Player")
{
_player.GetComponent<PlayerManager>().canSipa = true;
}
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.gameObject.tag == "Player")
{
_player.GetComponent<PlayerManager>().canSipa = false ;
}
}
}
add a second collider, slightly larger then the first, mark it trigger. leave the smaller inner collider for physics. you "foot" should enter the trigger and activiate it, then collide with the inner collider. make sure the collider marked trigger is the larger one.
So I want my player to be able to travel up and down ladders without falling off unintentionally. Climbing up is easy enough, just let them walk forward against a wall and they'll collide and stay still but when they descend using the 'back' button they will start descending very briefly but immediately walk off the ladder. Disabling the player script temporarily is a messy process so I wanted to know what a good alternative is.
I'm using transform to raise and lower my player in the ladderScript and to move it in the playerScript.
Script (amended for brevity)
public class LadderScript : MonoBehaviour {
private playerScript pScript; //<--These both contain the colliding players script...
private Collider collided; //<---- ...and collider when Update runs
private bool triggerStay; //used to prevent Update from running while there is no contact
void Start()
{
triggerStay = false;
}
...
void Update() //Runs once per collider that is touching the player every frame
{
if (triggerStay) {
if (collided.CompareTag ("Player")) { //A player is touching the ladder
/*
if (!pScript.getIsGrounded ()) { //Ineffective
pScript.enabled = false;
} else if (pScript.getIsGrounded ()) {
pScript.enabled = true;
}
*/
if (Input.GetAxis ("Vertical") < 0) { // Player should go down
collided.transform.Translate (0, -.1f, 0);
} else if (Input.GetAxis ("Vertical") > 0) //Player should go up
collided.transform.Translate (0, .1f, 0);
}
}
}
...
}
I want the player to jump when the player is grounded.
private void OnTriggerStay(Collider other)
{
if(other.gameObject.layer == 8)
{
isGrounded = true;
}else { isGrounded = false; }
}
The player is on air when spawning. After the player falls to the Terrain, which has the tag Ground, isGrounded is still false. When I set isGrounded manually true and jump again, it's still true after collision. I also don't want the player to double jump in the air, which I probaly already coded but is not working because something is wrong.
Changing OnTriggerStay to OnTriggerEnter doesn't change something. I hope you can help me.
Do not use OnTriggerStay to do this. That's not guaranteed to be true very time.
Set isGrounded flag to true when OnCollisionEnter is called. Set it to false when OnCollisionExit is called.
bool isGrounded = true;
private float jumpForce = 2f;
private Rigidbody pRigidBody;
void Start()
{
pRigidBody = GetComponent<Rigidbody>();
}
private void Update()
{
if (Input.GetButtonDown("Jump") && isGrounded)
{
pRigidBody.AddForce(new Vector3(0, jumpForce, 0));
}
}
void OnCollisionEnter(Collision collision)
{
Debug.Log("Entered");
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = true;
}
}
void OnCollisionExit(Collision collision)
{
Debug.Log("Exited");
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = false;
}
}
Before you say it doesn't work, please check the following:
You must have Rigidbody or Rigidbody2D attached to the player.
If this Rigidbody2D, you must use OnCollisionEnter2D and
OnCollisionExit2D.
You must have Collider attached to the player with IsTrigger
disabled.
Make sure you are not moving the Rigidbody with the transform such
as transform.position and transform.Translate. You must move
Rigidbody with the MovePosition function.
Use this to check if collision is detected at all, it's good starting point for further debuging:
private void OnTriggerStay(Collider other)
{
Debug.Log(other);
}
You must have Collider attached to the player with IsTrigger disabled.
I think you mean enabled? I was struggling to get this to work but as soon as I enabled the collider's IsTrigger it started actually working. The OnTriggerEnter/Exit doesn't seem to do very much on a collider that isn't actually a trigger...