im developing a game right now. It seems more like capture the flag in 2d. But im having problem with my character script. what i want is if my character has the flag and he goes back to her base with a flag(gameobject on) she will go to the winscene. but the thing is i also want her to not proceed to the winscene when the gameobject is not on.
Here's the Script
GameObject[] toEnable, toDisable;
public GameObject CharFlag;
private Rigidbody2D rb;
private Animator anim;
private float moveSpeed;
private float dirX;
private bool facingRight = true;
private Vector3 localScale;
//Use this for Initialization
private void Start(){
rb = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
localScale = transform.localScale;
moveSpeed = 5f;
// Finding game objects with tags "ToEnable" and "ToDisable"
toEnable = GameObject.FindGameObjectsWithTag ("CharFlag");
// Disabling game objects with tag "ToEnable"
foreach (GameObject element in toEnable)
{
element.gameObject.SetActive (false);
}
}
//Update is called once per frame
private void Update()
{
dirX = CrossPlatformInputManager.GetAxisRaw ("Horizontal") * moveSpeed;
if (CrossPlatformInputManager.GetButtonDown ("Jump") && rb.velocity.y == 0)
rb.AddForce(Vector2.up * 700f);
if (Mathf.Abs(dirX) > 0 && rb.velocity.y == 0)
anim.SetBool("isRunning", true);
else
anim.SetBool("isRunning", false);
if (rb.velocity.y == 0)
{
anim.SetBool("isJumping", false);
anim.SetBool("isFalling", false);
}
if (rb.velocity.y > 0)
{
anim.SetBool("isJumping", true);
}
if (rb.velocity.y < 0)
{
anim.SetBool("isJumping", false);
anim.SetBool("isFalling", true);
}
}
private void FixedUpdate()
{
rb.velocity = new Vector2(dirX, rb.velocity.y);
}
private void LateUpdate()
{
if (dirX > 0)
facingRight = true;
else if (dirX < 0)
facingRight = false;
if (((facingRight) && (localScale.x < 0)) || ((!facingRight) && (localScale.x > 0)))
localScale.x *= -1;
transform.localScale = localScale;
}
void OnTriggerEnter2D (Collider2D col)
{
switch (col.tag) {
case "EnemyField":
CharFlag.gameObject.SetActive (true);
break;
case "AlyField":
SceneManager.LoadScene ("YouWin");
break;
}
}
}
This would be better as a comment but I only have 40 reputation.
Simply check if the GameObject is active or not.
switch (col.tag)
{
case "EnemyField":
CharFlag.gameObject.SetActive (true);
break;
case "AllyField":
if(CharFlag.gameObject.activeSelf)
{
SceneManager.LoadScene ("YouWin");
}
break;
Related
I'm new to C#, I'm making a game to learn.
Can anyone help me, I found some scripts on the web for my player. I tried to make animations for it and I used the "Bool", but sometimes when the player starts to walk it doesn't get animated. What can I do?
I added the flip to flip the player left and right. And I added the "If" with the SetBool for the transition from "Idle" to "IsWalking".
Screenshot of my animator
My player has 4 scripts.
The other 3 are in the following link: [Link] (https://drive.google.com/drive/folders/1F_zbQJgihv82zjg5pcQ9L_dp0sgA2O2Q?usp=sharing)
using UnityEngine;
using System.Collections;
[RequireComponent (typeof (Player))]
public class PlayerInput : MonoBehaviour {
private Animator anim;
private bool m_FacingRight = true;
void Start () {
player = GetComponent<Player> ();
anim = GetComponent<Animator>();
}
void Update () {
Vector2 directionalInput = new Vector2 (Input.GetAxisRaw ("Horizontal"), Input.GetAxisRaw ("Vertical"));
player.SetDirectionalInput (directionalInput);
if (Input.GetAxisRaw("Horizontal") > 0 && !m_FacingRight)
{
Flip();
anim.SetBool("IsWalking", true);
}
if (Input.GetAxisRaw("Horizontal") < 0 && m_FacingRight)
{
Flip();
anim.SetBool("IsWalking", true);
}
if (Input.GetAxisRaw("Horizontal") == 0 && !m_FacingRight)
{
anim.SetBool("IsWalking", false);
}
if (Input.GetAxisRaw("Horizontal") == 0 && m_FacingRight)
{
anim.SetBool("IsWalking", false);
}
if (Input.GetKeyDown (KeyCode.Space)) {
player.OnJumpInputDown ();
anim.SetBool("IsJumping", true);
}
if (Input.GetKeyUp (KeyCode.Space)) {
player.OnJumpInputUp ();
anim.SetBool("IsJumping", false);
}
}
private void Flip()
{
// Switch the way the player is labelled as facing.
m_FacingRight = !m_FacingRight;
// Multiply the player's x local scale by -1.
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerInput : MonoBehaviour
{
private Animator anim;
private bool _right ;
private bool _left ;
public float MoveSpeed;
void Start()
{
anim = GetComponent<Animator>();
player = GetComponent<Player> ();
}
void Update()
{
Vector2 directionalInput = new Vector2(Input.GetAxisRaw("Horizontal")*Time.deltaTime, Input.GetAxisRaw("Vertical") * Time.deltaTime);
player.SetDirectionalInput (directionalInput);
if (Input.GetAxisRaw("Horizontal") > 0)
{
TurnRight();
anim.SetBool("IsWalking", true);
}
if (Input.GetAxisRaw("Horizontal") < 0)
{
TurnLeft();
anim.SetBool("IsWalking", true);
}
if (Input.GetAxisRaw("Horizontal") == 0)
{
anim.SetBool("IsWalking", false);
}
if (Input.GetKeyDown (KeyCode.Space)) {
player.OnJumpInputDown ();
anim.SetBool("IsJumping", true);
}
if (Input.GetKeyUp (KeyCode.Space)) {
player.OnJumpInputUp ();
anim.SetBool("IsJumping", false);
}
}
public void TurnRight()
{
if (_right) return;
transform.localScale = new Vector3(Mathf.Abs(transform.localScale.x), transform.localScale.y, 0);
_right = true;
_left = false;
}
public void TurnLeft()
{
if (_left) return;
transform.localScale = new Vector3(-transform.localScale.x, transform.localScale.y, 0);
_left = true;
_right = false;
}
}
there is some problems in your script.
For Example Once I start moving right, m_FacingRight will be true, and then I stop moving. Still, m_FacingRight is true. Since m_FacingRight is still true, if I start moving to the right again, the animation of walk will not play. Because you have used
if (Input.GetAxisRaw("Horizontal") > 0 && !m_FacingRight)
Same for the left side
Working on a platformer where as the player moves over an energy orb, they can choose to fuel either a double jump or a dash. No errors according to unity, but when I press the corresponding keys for my double jump and dash, neither work. Simply nothing happens. Oh and btw my character randomly freezes and I have to tap the movement key again to get him to continue moving this is also a new issue so may be related. I am very new to all this.
public class playerMovement : MonoBehaviour
{
[SerializeField] private float speed;
[SerializeField] int dashEnergy = 1;
[SerializeField] int doubleJumpEnergy = 1;
private Rigidbody2D body;
private Animator anim;
private int jumpCount;
private void Awake()
{
body = GetComponent<Rigidbody2D>();
}
private void Update()
{
//Left-Right Movement
float horizontalInput = Input.GetAxis("Horizontal");
if(Input.GetKey(KeyCode.Space) && jumpCount == 0)
{
jump();
jumpCount += 1;
}
body.velocity = new Vector2(horizontalInput*speed, body.velocity.y);
//Character Turns Towards Movement Direction
if (horizontalInput > 0.01f)
transform.localScale = new Vector3(-5, 5, 5);
if (horizontalInput < -0.01f)
transform.localScale = new Vector3(5,5,5);
//Dash & doubleJump
void doubleJump()
{
if(Input.GetKey(KeyCode.Space)&&jumpCount==1 && doubleJumpEnergy==1)
{
jump();
doubleJumpEnergy -= 1;
}
}
void Dash()
{
if(Input.GetKey(KeyCode.LeftShift) && dashEnergy == 1)
{
body.velocity = new Vector2(horizontalInput*speed*60, body.velocity.y);
dashEnergy -=1;
}
}
}
public void jump()
{
body.velocity = new Vector2(body.velocity.x, speed);
}
private void OnCollisionEnter2D(Collision2D collision)
{
if(collision.gameObject.tag == "EnergyBubble" && Input.GetKey(KeyCode.V))
{
dashEnergy += 1;
}
if(collision.gameObject.tag == "EnergyBubble" && Input.GetKey(KeyCode.C))
{
doubleJumpEnergy += 1;
}
if (collision.gameObject.tag == "Ground")
{
jumpCount=0;
}
}
}
Firstly, all physics operations should be used from fixedUpdate method, for example:
void FixedUpdate()
{
if (Input.GetButtonDown("Space"))
rb.velocity = new Vector2(0, 10);
}
It's needs for smoothly physics movement.
Or call your own method from it:
void FixedUpdate()
{
if (Input.GetButtonDown("Space"))
jump();
}
Then you have a bug in condition check statements, you have to use:
//Dash & doubleJump
if (Input.GetKey(KeyCode.Space) && jumpCount == 1 && doubleJumpEnergy >= 1)
{
body.velocity = new Vector2(0, 2);
doubleJumpEnergy -= 1;
}
if (Input.GetKey(KeyCode.LeftShift) && dashEnergy >= 1)
{
body.velocity = new Vector2(horizontalInput * speed * 60, body.velocity.y);
dashEnergy -= 1;
}
Problem with a condition check statements, you need to have ">=" operator: dashEnergy >= 1 and doubleJumpEnergy >= 1 instead ==
I have been coding a game for about an hour now and I have run into an error with my script that I can't seem to fix. What I mainly seem to be focusing on is the isGrounded update part of my script:
private void OnCollisionExit2D(Collision2D collision)
{
isGrounded = false;
}
private void OnCollisionEnter2D(Collision2D collision2)
{
isGrounded = true;
}
But I am concerned it might be a different part of my script because I don't think anything is wrong with this part. Here is the full script:
using UnityEngine;
using System.Collections;
public class move : MonoBehaviour
{
public float speed;
float moveVelocity;
public float jumpPower = 300.0f;
private bool isGrounded = false;
private bool facingEast = false;
void Update()
{
moveVelocity = 0;
//Left Right Movement
if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.A))
{
moveVelocity = -speed;
facingEast = false;
}
if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.D))
{
moveVelocity = speed;
facingEast = true;
}
GetComponent<Rigidbody2D>().velocity = new Vector2(moveVelocity, GetComponent<Rigidbody2D>().velocity.y);
Rigidbody2D rb = GetComponent<Rigidbody2D>();
if (Input.GetKeyDown(KeyCode.UpArrow) || Input.GetKeyDown(KeyCode.Space))
{
if (isGrounded == true)
{
rb.AddForce(Vector2.up * jumpPower);
}
}
}
private void OnCollisionExit2D(Collision2D collision)
{
isGrounded = false;
}
private void OnCollisionEnter2D(Collision2D collision2)
{
isGrounded = true;
}
}
Sorry if this is a bad question or if there is an obvious answer and I am just being stupid. I am still fairly new to C#
In general in OnCollisionEnter2D and OnCollisionExit2D you should check what you are colliding with!
e.g. using Tags and CompareTag like
private void OnCollisionExit2D(Collision2D collision)
{
if(!collision.transform.CompareTag("Ground")) return;
// only do this if the thing you don't collide
// anymore is actually the ground
isGrounded = false;
}
private void OnCollisionEnter2D(Collision2D collision2)
{
if(!collision.transform.CompareTag("Ground")) return;
// only do this if the thing you collided with is actually the ground
isGrounded = true;
}
otherwise what happens when you collide with a wall is a OnCollisionEnter2D followed by a OnCollisionExit2D => isGrounded = false;
Also in general: Don't use GetComponent in Update and especially not for getting the same reference in 3 different places!
Rather get it once in Awake or already assign it via the Inspector
// already assign via the Inspector by drag&drop
[SerializeField] private Rigidbody2D _rigidbody;
// as fallback assign ONCE in the beginning
private void Awake()
{
if(!_rigidbody) _rigidbody = GetComponent<Rigidbody2D>();
}
and later reuse it
void Update()
{
moveVelocity = 0;
//Left Right Movement
if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.A))
{
// I would use -= and += here so when pressing both buttons
// you simply stay at 0. But that's only my opinion of course
// Alternatively I would use 'else if' in order to make the blocks exclusive
moveVelocity -= speed;
facingEast = false;
}
if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.D))
{
moveVelocity += speed;
facingEast = true;
}
_rigidbody.velocity = new Vector2(moveVelocity, _rigidbody.velocity.y);
// here it is cheeper to first check the isGrounded flag
// and only if it is true get the input
if (isGrounded && (Input.GetKeyDown(KeyCode.UpArrow) || Input.GetKeyDown(KeyCode.Space)))
{
_rigidbody.AddForce(Vector2.up * jumpPower);
}
}
So I'm trying to add a dash mechanic to a game character im building. However for some reason i can't get the game objects velocity to actually change. I tried using addForce which worked, but i had to add a lot in order to get the desired effect and that behaved strangely sometimes!
Do i need to do anything else to the game objects velocity than i already doing?
Heres my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float dashSpeed;
private int dashDirection;
private float dashCoolDown;
public float startDashCoolDown;
private float dashTime;
public float startDashTime;
public GameObject dashEffect;
public float speed;
public float jumpForce;
private float moveInput;
private Rigidbody2D rb;
private bool isFacingRight = true;
private Animator anim;
private bool isGrounded;
public Transform groundCheck;
public float checkRadius;
public LayerMask whatIsGround;
private int extraJumps;
public int extraJumpsValue;
public GameObject dustEffect;
public GameObject trailEffect;
private void Awake()
{
// Setting up references.
isGrounded = transform.Find("GroundCheck");
anim = GetComponent<Animator>();
rb = GetComponent<Rigidbody2D>();
}
void Start()
{
extraJumps = extraJumpsValue;
rb = GetComponent<Rigidbody2D>();
dashTime = startDashTime;
dashCoolDown = startDashCoolDown;
}
void FixedUpdate()
{
isGrounded = false;
// Check to see if grounded
Collider2D[] colliders = Physics2D.OverlapCircleAll(groundCheck.position, checkRadius, whatIsGround);
for (int i = 0; i < colliders.Length; i++)
{
if (colliders[i].gameObject != gameObject)
{
isGrounded = true;
anim.SetBool("Ground", isGrounded);
}
}
// Check if movement is allowed
if (!GameMaster.disableMovement)
{
// Move character
moveInput = Input.GetAxis("Horizontal");
rb.velocity = new Vector2(moveInput * speed, rb.velocity.y);
Instantiate(trailEffect, groundCheck.position, Quaternion.identity);
anim.SetFloat("Speed", Mathf.Abs(moveInput));
}
// Flip character
if (isFacingRight == false && moveInput > 0)
{
Flip();
}
else if (isFacingRight == true && moveInput < 0)
{
Flip();
}
}
private void Update()
{
// Check if the player is grounded
if (isGrounded == true)
{
extraJumps = extraJumpsValue;
}
// Check if movement is allowed
if (!GameMaster.disableMovement)
{
// Check for jump
// If the player has more than one jump available
if (Input.GetKeyDown(KeyCode.Space) && extraJumps > 0)
{
isGrounded = false;
anim.SetBool("Ground", isGrounded);
rb.velocity = Vector2.up * jumpForce;
extraJumps--;
Instantiate(dustEffect, groundCheck.position, Quaternion.identity);
}
// If the player only has one jump available
if (Input.GetKeyDown(KeyCode.Space) && extraJumps == 0 && isGrounded == true)
{
isGrounded = false;
anim.SetBool("Ground", isGrounded);
rb.velocity = Vector2.up * jumpForce;
}
// Check for dash
if (dashCoolDown <= 0)
{
if (Input.GetKeyDown(KeyCode.LeftShift))
{
anim.SetBool("Dash", true);
Dash();
dashTime = startDashTime;
}
}
else
{
dashCoolDown -= Time.deltaTime;
}
}
}
void Dash()
{
if (dashTime <= 0)
{
dashCoolDown = startDashCoolDown;
anim.SetBool("Dash", false);
}
else
{
dashTime -= Time.deltaTime;
if (isFacingRight)
{
rb.velocity = Vector2.right * dashSpeed;
}
else if (!isFacingRight)
{
rb.velocity = Vector2.left * dashSpeed;
}
}
}
void Flip()
{
isFacingRight = !isFacingRight;
// Multiply the player's x local scale by -1.
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
If you dont get the desired dash effect with Rigidbody.velocity, you can try using Rigidbody.addForce(). I know you said you already used it, but there are multiple different force modes you can apply here. I would suggest using this one, because it applies full force from the start and then drops it off. You can read more about it yourself here.
So you could modify your code like so:
void Dash()
{
if (isFacingRight)
{
rb.AddForce(Vector2.right*dashSpeed, ForceMode.VelocityChange);
}
else if (!isFacingRight)
{
rb.AddForce(Vector2.left*dashSpeed, ForceMode.VelocityChange);
}
}
Note, that you also dont need to call dash repeatedly to falloff the velocity. this function should now be only called onse the button to dash (shift) has been pressed.
Hope this helped!
I'm making a 2D platformer in Unity, and made a patrolling enemy with code from a tutorial video. The enemy basically moves randomly to different spots in the scene. But how can I make the sprite turn around?
This is my code so far. I've tried with different approaches, but not getting the expected behavior.
public float speed = 10f;
private float waitTime;
public float startWaitTime = 1f;
public Transform[] moveSpots;
private int randomSpot;
private bool moving = true;
private bool m_FacingRight = true;
void Start()
{
waitTime = startWaitTime;
randomSpot = Random.Range(0, moveSpots.Length);
}
void Update()
{
transform.position = Vector2.MoveTowards(transform.position, moveSpots[randomSpot].position, speed * Time.deltaTime);
if (Vector2.Distance(transform.position, moveSpots[randomSpot].position) < 0.2f)
{
//Debug.Log(m_FacingRight);
// if (moving.x > 0 && !m_FacingRight)
// {
// Debug.Log("moving right");
// Flip();
// }
// else if (moving.x < 0 && m_FacingRight)
// {
// Debug.Log("moving left");
// Flip();
// }
if (waitTime <= 0)
{
//moving = true;
randomSpot = Random.Range(0, moveSpots.Length);
waitTime = startWaitTime;
}
else
{
//moving = false;
waitTime -= Time.deltaTime;
}
}
}
//private void Flip()
//{
//m_FacingRight = !m_FacingRight;
//transform.Rotate(0f, 180f, 0f);
//}
**********************************EDIT****************************************
I ended up with this for the enemy script movement
private bool facingRight = true;
private Rigidbody2D rigidBody2D;
private SpriteRenderer spriteRenderer;
public Vector2 speed = new Vector2(10, 0);
public Vector2 direction = new Vector2(1, 0);
private void Awake()
{
rigidBody2D = GetComponent<Rigidbody2D>();
spriteRenderer = GetComponent<SpriteRenderer>();
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.CompareTag("Wall") || collision.collider.CompareTag("Player"))
{
direction = Vector2.Scale(direction, new Vector2(-1, 0));
}
if (!collision.collider.CompareTag("Ground"))
{
if (!facingRight)
{
Flip();
}
else if (facingRight)
{
Flip();
}
}
}
void FixedUpdate()
{
Vector2 movement = new Vector2(speed.x * direction.x, 0);
movement *= Time.deltaTime;
transform.Translate(movement);
}
private void Flip()
{
facingRight = !facingRight;
if (!facingRight)
{
spriteRenderer.flipX = true;
}
else if (facingRight)
{
spriteRenderer.flipX = false;
}
}
Rewrite your Flip function to
private void Flip()
{
m_FacingRight = !m_FacingRight;
GetComponent<SpriteRenderer>().flipX = true;
}
Also, if you're looking for a reference, I made a platformer in Unity that includes enemy patrolling https://github.com/sean244/Braid-Clone
In a sidescroller, an easy way to achieve this is to use SpriteRenderer.flipX.
For instance, if you want to flip X when the velocity is negative:
var sr = GetComponent<SpriteRenderer>();
sr.flipX = velocity.x < 0;