How do I stop the player partly going through ground - c#

I made a controller for a 2d character, I fixed the issue of the player jittering through the wall but I cant fix the player jittering through the ground. Got this code from multiple tutorials and tweaking stuff. If you have any tips that would be greatly appreciated I'm new to this stuff and working on my first game (had to ramble cuz I put too much code) thanks.
{
public float speed, height;
Rigidbody2D rb;
private bool horizontalRight = false;
private bool horizontalLeft = false;
private bool verticalMove = false;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
if (Input.GetAxisRaw("Horizontal") > 0)
{
horizontalRight = true;
}
else if (Input.GetAxisRaw("Horizontal") < 0)
{
horizontalLeft = true;
}
if (Input.GetButton("Jump") && rb.velocity.y == 0)
{
verticalMove = true;
}
}
private void FixedUpdate()
{
if (horizontalRight == true)
{
transform.Translate(Vector2.right * Time.deltaTime * speed);
horizontalRight = false;
}
else if (horizontalLeft == true)
{
transform.Translate(Vector2.left * Time.deltaTime * speed);
horizontalLeft = false;
}
if (verticalMove == true)
{
rb.velocity = new Vector2(0, height);
verticalMove = false;
}
}
}

Activate continuous collision detection on your rigid bodies, it'll keep them from phasing through things so long as they're being moved via their velocity.

A typical jump in unity would look like:
void Jump()
{
if (_isGrounded == true)
{
rb.AddForce(Vector2.up * _jumpSpeed);
_isGrounded = false;
}
}
and in collision event
void OnCollisionEnter (Collision hit)
{
_isGrounded = true;
}
this would limit when you can use a jump.

Related

Unity Simple Sliding Door. Collider moving but not the actual object

I have been trying to make an automatic door when the player walks close to the door it will automatically open and then close after leaving that area. I have tried it different ways with having a different object as a collision sensor to move the door to even using a box collider on the door itself but it doesn't work. The Collider will move but you will be phasing through the door after.
public float maximumOpening = 3;
public float maximumClosing = 0;
public float movementSpeed = 1;
bool playerIsHere;
bool opening;
void Start()
{
playerIsHere = false;
opening = false;
}
void Update()
{
if(playerIsHere)
{
if (movingDoor.transform.position.x < maximumOpening)
{
movingDoor.transform.position += Vector3.forward * Time.deltaTime;
}
else
{
if (movingDoor.transform.position.x > maximumClosing)
{
movingDoor.transform.position += -Vector3.forward * Time.deltaTime;
}
}
}
}
private void OnTriggerEnter(Collider col)
{
if(col.gameObject.tag == "Player")
{
playerIsHere = true;
}
}
private void OnTriggerExit(Collider col)
{
if (col.gameObject.tag == "Player")
{
playerIsHere = false;
}
}
!https://imgur.com/a/C4AmoUl
Shouldn't it be more like the following:
if (playerIsHere && movingDoor.transform.position.x < maximumOpening)
{
movingDoor.transform.position += Vector3.forward * Time.deltaTime;
}
else if (movingDoor.transform.position.x > maximumClosing)
{
movingDoor.transform.position += -Vector3.forward * Time.deltaTime;
}
since otherwise the door will only do anything when the player is actually in it, and otherwise do nothing, hope it helps :)

problems with enemy melee

I've been working on a 2d game for weeks and nothing works. I'm not the best coder out there I'm still learning! In my game I have a player and then an enemy. I need the enemy to behave by itself so I've been following many youtube tutorials, however, it seems that all of them have some sort of problem. I have checked for spelling and everything but still no result. I followed this tutorial (https://www.youtube.com/watch?v=waj6i9cQ6rM) lately but it doesn't work for me. My enemy just plays the attack animation over and over when the player is not even close and it doesn't move from its position.
This is my code:
void EnemyLogic()
{
distance = Vector2.Distance(transform.position, target.transform.position);
if(distance > attackDistance)
{
Move();
StopAttack();
}
else if (attackDistance >= distance && cooling == false)
{
Attack();
}
if (cooling)
{
Cooldown();
Animator.SetBool("Attack", false);
}
}
void Move()
{
Animator.SetBool("canWalk", false);
if(!Animator.GetCurrentAnimatorStateInfo(0).IsName("LightBandit_Attack"))
{
Vector2 targetPosition = new Vector2(target.transform.position.x, transform.position.y);
transform.position = Vector2.MoveTowards(transform.position, targetPosition, moveSpeed * Time.deltaTime);
}
}
void Attack()
{
timer = intTimer; // reset time when player is in rnge
attackMode = true; // check if enemy can still attack or not
Animator.SetBool("canWalk", false);
Animator.SetBool("attack", true);
//Player.GetComponent<HeroKnight>()?.TakeDamage(attackDamage);
}
void Cooldown()
{
timer -= Time.deltaTime;
if(timer <= 0 && cooling && attackMode)
{
cooling = false;
timer = intTimer;
}
}
void StopAttack()
{
cooling = false;
attackMode = false;
Animator.SetBool("attack", false);
}
void RaycastDebugger()
{
if(distance > attackDistance)
{
Debug.DrawRay(rayCast.position, Vector2.left * rayCastLength, Color.red);
}
else if (attackDistance > distance)
{
Debug.DrawRay(rayCast.position, Vector2.left * rayCastLength, Color.green );
}
}
public void TriggerCooling()
{
cooling = true;
}
You have written a condition here that does not allow movement to occur. Eliminate this condition and limit the enemy logic to distances only.
if (!Animator.GetCurrentAnimatorStateInfo(0).IsName("LightBandit_Attack"))

The enemy flies through the walls

I wrote a code for an enemy that, when he sees my character, will chase him. But when he sees my character and chases him, he goes through objects.There is a box collider 2D on it, but it moves with it. I've already tried everything, I don't know how to fix it. Can you please help fix
Here is my code:
void Start()
{
player = GameObject.FindGameObjectWithTag("Player").transform;
idleSpeed = speed;
barDelta = Vector3.Distance(parent.position, barPoint.position);
bar = UIManager.AddEnemy(this);
}
void Update()
{
if (Vector2.Distance(transform.position, point.position) < positionOfPatrol && angry == false)
{
idle = true;
}
if (Vector2.Distance(transform.position, player.position) < stoppingDistance)
{
angry = true;
idle = false;
goBack = false;
}
if (Vector2.Distance(transform.position, player.position) > stoppingDistance)
{
goBack = true;
angry = false;
}
if (idle == true)
{
Idle();
}
else if (angry == true)
{
Angry();
}
else if (goBack == true)
{
GoBack();
}
}
void Idle()
{
if (transform.position.x > point.position.x + positionOfPatrol)
{
moveingRight = false;
}
else if (transform.position.x < point.position.x - positionOfPatrol)
{
moveingRight = true;
}
if (moveingRight)
{
if (!facingRight) Flip();
facingRight = true;
transform.position = new Vector2(transform.position.x + speed * Time.deltaTime, transform.position.y);
}
else
{
if (facingRight) Flip();
facingRight = false;
transform.position = new Vector2(transform.position.x - speed * Time.deltaTime, transform.position.y);
}
}
void Angry()
{
transform.position = Vector2.MoveTowards(transform.position, player.position, speed * Time.deltaTime);
speed = idleSpeed + 1;
}
void GoBack()
{
transform.position = Vector2.MoveTowards(transform.position, point.position, speed * Time.deltaTime);
speed = idleSpeed;
}
}
You should try to use a rigidbody with the collider. The collider does not actually do physics, that is what the rigidbody is for. If you add a rigidbody and set its velocity instead of setting the transform's position, it will not only detect collisions with walls but it will stop moving and do all of the physics you would expect.

How to prevent any player Input if the object is moving

I am creating a clone of Billiards and I cannot work out how to stop the player from interacting with and launching the ball while it is still moving; below is my attempt. I have placed an if statement that checks whether the ball is moving on both the mouseDrag and mouseUp functions. I have also tried using isSleeping() but this caused the ball to not move at all.
If possible I would like to apply this method to all of the balls and not just the cue ball; so that all balls have to have stopped before any actions may happen. This is currently in my "player" script, if I should move it a GameManager script please let me know.
private void Update()
{
speed = rb.velocity.magnitude;
if (speed < 0.5)
{
rb.velocity = new Vector3(0, 0, 0);
}
}
void OnMouseDrag()
{
if (speed == 0)
{
mousePointB.GetComponent<SpriteRenderer>().enabled = true;
currDistance = Vector3.Distance(mousePointA.transform.position, transform.position);
if (currDistance <= 3f)
{
spaceLimit = currDistance;
}
else
{
spaceLimit = maxDistance;
}
shootPower = Mathf.Abs(spaceLimit) * shootPowervar;
Vector3 dimxy = mousePointA.transform.position - transform.position;
float difference = dimxy.magnitude;
mousePointB.transform.position = transform.position + ((dimxy / difference) * currDistance * -1);
mousePointB.transform.position = new Vector3(mousePointB.transform.position.x, mousePointB.transform.position.y, -0.8f);
shootDirection = Vector3.Normalize(mousePointA.transform.position - transform.position);
}
else
{
}
}
void OnMouseUp()
{
if (speed == 0)
{
mousePointB.GetComponent<SpriteRenderer>().enabled = false;
arrow.GetComponent<SpriteRenderer>().enabled = false;
circle.GetComponent<SpriteRenderer>().enabled = false;
Vector3 push = shootDirection * shootPower * -1;
GetComponent<Rigidbody2D>().AddForce(push, ForceMode2D.Impulse);
}
else
{
}
}
if your test speed == 0 is not functional, you could record the last position of the ball, and set a boolean isMoving = true, if actual position of ball is different thant the last, then record the lastposition and so on
Vector3 LastPosition;
bool isMoving;
void Update()
{
isMoving = BallPosition == LastPosition;
:
:
}
void OnMOuseDrag()
{
if(!isMoving) return;
}
void OnMOuseUp()
{
if(!isMoving) return;
}

Crouching issues in Unity

So I've created crouching in Unity 2D game, everything goes well except when there is something above the character after exiting crouching, what it does is that it returns to idle animation and decreases Y-axis position, I know that is normal but how can I keep the character crouched when there is something above him or when I hold the ctrl button? Check the script down below if necessary. Thanks!
private Rigidbody2D rb2d;
private float h = 0.0f;
public float Speed, Jump;
private bool canJump;
private Animator anim;
private BoxCollider2D bc2d;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
bc2d = GetComponent<BoxCollider2D>();
}
// Update is called once per frame
void Update()
{
h = Input.GetAxisRaw("Horizontal");
anim.SetFloat("Speed", Mathf.Abs(h));
transform.Translate(Vector3.right * h * Speed * Time.deltaTime);
if (h != 0.0f)
{
transform.localScale = new Vector2(h, transform.localScale.y);
}
if (Input.GetKeyDown(KeyCode.Space) && canJump == true)
{
rb2d.AddForce(new Vector2(rb2d.velocity.x, Jump));
}
if (Input.GetKeyDown(KeyCode.LeftControl))
{
bc2d.enabled = false;
Speed = Speed / 2;
anim.SetBool("Crouch", true);
}
else if (Input.GetKeyUp(KeyCode.LeftControl))
{
bc2d.enabled = true;
Speed = Speed * 2;
anim.SetBool("Crouch", false);
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.name == "Ground")
{
canJump = true;
anim.SetBool("Jump", false);
}
}
private void OnCollisionExit2D(Collision2D collision)
{
if (collision.collider.name == "Ground")
{
canJump = false;
anim.SetBool("Jump", true);
}
}
Use RaycastHit2D. Basically before "standing" cast a ray Vector2.up from the character and if it hits, check to make sure there's enough room to stand. Something like:
private Rigidbody2D rb2d;
private Transform t;
private float h = 0.0f;
public float Speed, Jump;
private bool canJump;
private Animator anim;
private BoxCollider2D bc2d;
// Variable to check if character is attempting to stand
private bool tryingToStand = false;
// Keep crouching state
private bool isCrouching = false;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
bc2d = GetComponent<BoxCollider2D>();
t = GetComponent<Transform>();
}
// Update is called once per frame
void Update()
{
h = Input.GetAxisRaw("Horizontal");
anim.SetFloat("Speed", Mathf.Abs(h));
transform.Translate(Vector3.right * h * Speed * Time.deltaTime);
if (h != 0.0f)
{
transform.localScale = new Vector2(h, transform.localScale.y);
}
// Make sure we can jump and we're not crouching before jumping
if (Input.GetKeyDown(KeyCode.Space) && canJump == true && !isCrouching)
{
rb2d.AddForce(new Vector2(rb2d.velocity.x, Jump));
}
if (Input.GetKeyDown(KeyCode.LeftControl))
{
bc2d.enabled = false;
anim.SetBool("Crouch", true);
// Make sure we haven't already halved the speed
if (!tryingToStand)
{
Speed = Speed / 2;
}
// Set tryingToStand to false in case player holds ctrl before character has stood up
tryingToStand = false;
// Set crouching state to true
isCrouching = true;
}
else if (Input.GetKeyUp(KeyCode.LeftControl))
{
tryingToStand = true;
}
if (tryingToStand && CanStand())
{
tryingToStand = false;
// Set crouching state to false;
isCrouching = false;
bc2d.enabled = true;
Speed = Speed * 2;
anim.SetBool("Crouch", false);
}
}
bool CanStand()
{
RaycastHit2D hit = Physics2D.Raycast(t.position, Vector2.up);
if (hit.collider != null)
{
// Check the distance to make sure the character has clearance, you'll have to change the 1.0f to what makes sense in your situation.
if (hit.distance <= 1.0f)
{
return false;
}
}
return true;
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.name == "Ground")
{
canJump = true;
anim.SetBool("Jump", false);
}
}
private void OnCollisionExit2D(Collision2D collision)
{
if (collision.collider.name == "Ground")
{
canJump = false;
anim.SetBool("Jump", true);
}
}

Categories

Resources