i made 2d character and 3 ui buttons and they worked well
but the problem is when moving to the right or left by the ui buttons i can't jump however when jump from the ui button i can move to right and left
this is the script
public class PlayerWalk : MonoBehaviour {
private PlayerAnimation playerAnim;
private Rigidbody2D myBody;
private SpriteRenderer spriteRenderer;
public float speed = 7f;
public float jumpForce = 7f;
private bool moveLeft; // determine if we move left or right
private bool dontMove; // determine if we are moving or not
private bool canJump; // we will test if we can jump
void Start () {
playerAnim = GetComponent<PlayerAnimation>();
myBody = GetComponent<Rigidbody2D>();
dontMove = true;
}
void Update () {
//DetectInput();
HandleMoving();
}
void HandleMoving() {
if (dontMove) {
StopMoving();
} else {
if (moveLeft) {
MoveLeft();
} else if (!moveLeft) {
MoveRight();
}
}
} // handle moving
public void AllowMovement(bool movement) {
dontMove = false;
moveLeft = movement;
}
public void DontAllowMovement() {
dontMove = true;
}
public void Jump() {
if(canJump) {
myBody.velocity = new Vector2(myBody.velocity.x, jumpForce);
//myBody.AddForce(Vector2.right * jumpForce);
}
}
// PREVIOUS FUNCTIONS
public void MoveLeft() {
myBody.velocity = new Vector2(-speed, myBody.velocity.y);
playerAnim.ZombieWalk(true, true);
}
public void MoveRight() {
myBody.velocity = new Vector2(speed, myBody.velocity.y);
playerAnim.ZombieWalk(true, false);
}
public void StopMoving() {
playerAnim.ZombieStop();
myBody.velocity = new Vector2(0f, myBody.velocity.y);
}
void DetectInput() {
float x = Input.GetAxisRaw("Horizontal");
if (x > 0)
{
MoveRight();
}
else if (x < 0)
{
MoveLeft();
}
else
{
StopMoving();
}
}
void OnCollisionEnter2D(Collision2D collision) {
if(collision.gameObject.tag == "Ground") {
canJump = true;
}
}
void OnCollisionExit2D(Collision2D collision) {
if (collision.gameObject.tag == "Ground") {
canJump = false;
}
}
} // class
the 2d character moves well and there is no bugs or problems with scripts
Any help??
I don't know where is the problem??
**Note ** i used unity5.6
I would say onTriggerEnter2D instead of using onCollisionEnter2D would be a better option in this scenario. You can read more about that here.
https://answers.unity.com/questions/875770/ontriggerenter-or-oncollisionenter-1.html#:~:text=OnCollisionEnter%20is%20called%20when%20two,with%20%22IsTrigger%22%20set).
Did you try to debug the value of canJump while you are trying to move left or right?
Related
I have a test ad setup in my unity game. I am calling the IntAd function from the GameManager Script after the game is over. But the problem is when I click the close button in the ad, the ad reappears again and again. Please help me how can stop IntAd function after showing the ad.
public class AdsManager : MonoBehaviour
{
public static AdsManager instance;
private string playStoreID = "000000";
private string intAd = "video";
private string rewardedAd = "rewardedVideo";
private string bannerAd = "bannerAd";
public bool isTargrtPlayStore;
public bool isTestAd;
public static int start;
void Awake()
{
DontDestroyOnLoad(this.gameObject);
if (instance == null)
{
instance = this;
}
else
{
Destroy(this.gameObject);
}
}
private void Start()
{
InitializeAdvertisement();
}
private void InitializeAdvertisement()
{
if (isTargrtPlayStore)
{
Advertisement.Initialize(playStoreID, isTestAd);
return;
}
}
public void IntAd()
{
if (Advertisement.IsReady(intAd))
{
Advertisement.Show(intAd);
}
}
}
Here is GameManager Script-
public class GameManager : MonoBehaviour
{
public static GameManager instance;
public bool gameOver;
void Awake()
{
if (instance == null){
instance = this;
}
}
// Start is called before the first frame update
void Start()
{
gameOver = false;
}
// Update is called once per frame
void Update()
{
}
public void StartGame()
{
UiManager.instance.GameStart();
UiManager.instance.StartScore1();
ScoreManager.instance.startScore();
GameObject.Find("PlatformSpawner").GetComponent<PlatformSpawner>().StartSpawningPlatforms();
//AdsManager.instance.BannerAd();
}
public void GameOver()
{
UiManager.instance.GameOver();
ScoreManager.instance.stopScore();
gameOver = true;
AdsManager.instance.IntAd();
}
}
code to call GameOver function
void Update()
{
if (!started)
{
if (Input.GetMouseButtonDown(0))
{
rb.velocity = new Vector3(speed, 0, 0);
started = true;
GameManager.instance.StartGame();
}
}
if (!Physics.Raycast(transform.position, Vector3.down, 1f))
{
gameOver = true;
rb.velocity = new Vector3(0, -25f, 0);
Camera.main.GetComponent<CameraFollow>().gameOver = true;
GameManager.instance.GameOver();
}
The code you have calling GameManager.GameOver() is inside of Update() so it's going to get called every frame, and if !Physics.Raycast(transform.position, Vector3.down, 1f) is always true when the game is over (and not just true once), then it'll end up calling GameManager.GameOver() every frame which lines up with the behaviour that you're seeing.
You could resolve this by adding !gameOver to your if statement, that way it'll only go into the if statement once at the end of your game, and then upon gamestart you could flip gameOver back to false.
if (!Physics.Raycast(transform.position, Vector3.down, 1f) && !gameOver)
{
gameOver = true;
rb.velocity = new Vector3(0, -25f, 0);
Camera.main.GetComponent<CameraFollow>().gameOver = true;
GameManager.instance.GameOver();
}
Just do an if statement with a bool named GameEnd. Set it to false. Play the ad only if GameEnd is false. Rite after the ad instantiates, set GameEnd to true.
if (!Physics.Raycast(transform.position, Vector3.down, 1f))
{
bool GameEnd = false;
gameOver = true;
rb.velocity = new Vector3(0, -25f, 0);
Camera.main.GetComponent<CameraFollow>().gameOver = true;
if(! GameEnd)
{
GameManager.instance.GameOver();
GameEnd = true;
}
}
I am creating a top down zombie shooter and I have made the zombie do damage to the player when it is touching the player. However when the player backs away from the zombie after taking damage, the players health will continue to drop. Any ideas on how to fix this would be appreciated.
public float moveSpeed= 5f;
public Rigidbody2D rb;
public Camera cam;
public float playerHealth = 100;
public float enemyDamage = 25;
public GameObject gameOverScreen;
Vector2 movement;
Vector2 mousePos;
// Update is called once per frame
void Update()
{
movement.x = Input.GetAxisRaw("Horizontal");
movement.y = Input.GetAxisRaw("Vertical");
mousePos = cam.ScreenToWorldPoint(Input.mousePosition);
if(playerHealth == 0)
{
gameOverScreen.SetActive(true);
}
}
void FixedUpdate()
{
rb.MovePosition(rb.position + movement * moveSpeed * Time.fixedDeltaTime);
Vector2 lookDir = mousePos - rb.position;
float angle = Mathf.Atan2(lookDir.y, lookDir.x) * Mathf.Rad2Deg - 90f;
rb.rotation = angle;
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Enemy"))
{
StartCoroutine(DamagePlayer());
}
else
{
StopCoroutine(DamagePlayer());
}
}
IEnumerator DamagePlayer()
{
while(true)
{
yield return new WaitForSeconds(1);
playerHealth -= enemyDamage;
}
}
First of all for doing something if it is not colliding anymore you should use OnCollisionExit2D
Then you can either use it the way you did using
StopCoroutine(DamagePlayer());
Or if want to be sure you could either store a reference to your routine
private Coroutine routine;
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Enemy"))
{
if(routine == null)
{
routine = StartCoroutine(DamagePlayer());
}
}
else
{
if(routine != null) StopCoroutine(routine);
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if(routine != null) StopCoroutine (routine);
}
or use a bool flag in order to terminate it
private bool cancelRoutine = true;
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Enemy"))
{
if(cancelRoutine) routine = StartCoroutine(DamagePlayer());
}
else
{
cancelRoutine = true;
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
cancelRoutine = true;
}
IEnumerator DamagePlayer()
{
cancelRoutine = false;
while(! cancelRoutine)
{
yield return new WaitForSeconds(1);
playerHealth -= enemyDamage;
}
}
In general you could solve this without a routine by directly using OnCollisionStay2D like e.g.
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Enemy"))
{
timer = 1;
}
}
void OnCollisionStay2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Enemy"))
{
timer -= Time.deltaTime;
if(timer <= 0)
{
timer = 1;
playerHealth -= enemyDamage;
}
}
}
I use a long press button, which works very well, on MouseDown and if I don't move the mouse, at the end of my delay, I have my action.
If I move the mouse (still pressing down and still on the button) it resets my button's delay, and I don't understand why.
if anyone has an idea, it would help me a lot.
Thx
Here's my code :
private bool _PointerDown;
public float DelaiReponse;
private float _PointerDownTimer;
private bool _IsValidate = false;
private float _Delai;
public void OnPointerDown(PointerEventData eventData)
{
_PointerDown = true;
}
public void OnPointerUp(PointerEventData eventData)
{
_PointerDown = false;
_PointerDownTimer = 0;
}
void Start()
{
_Delai = DelaiReponse;
}
private void Update()
{
if (_PointerDown) // Timer Button Validation Hold
{
_PointerDownTimer += Time.deltaTime;
if (_PointerDownTimer >= _Delai)
{
_IsValidate = true;
}
}
}enter code here
Using Input.GetMouseDown(0) and Input.GetMouseButtonUp(0) could fix the problem:
private void Update()
{
if (Input.GetMouseDown(0))
{
_PointerDown = true;
}
if (Input.GetMouseUp(0))
{
_PointerDown = false;
_PointerDownTimer = 0;
}
if (_PointerDown) // Timer Button Validation Hold
{
:
:
}
:
:
}
I finally found
OnMouseDown even worked outside my button, and I preferred the OnPointerDown method.
I added IDragHandler to my class, and create a bool _PointerDrag
private bool _PointerDown;
private bool _PointerDrag;
public float DelaiReponse;
private float _PointerDownTimer;
private bool _IsValidate = false;
private float _Delai;
public class LongClickButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler
{
public void OnPointerDown(PointerEventData eventData)
{
_PointerDown = true;
}
public void OnPointerUp(PointerEventData eventData)
{
_PointerDown = false;
_PointerDownTimer = 0;
}
public void OnDrag(PointerEventData eventData)
{
_PointerDrag = true;
}
void Start()
{
_Delai = DelaiReponse;
}
private void Update()
{
if (_PointerDown || _PointerDrag) // Timer Button Validation Hold
{
_PointerDownTimer += Time.deltaTime;
if (_PointerDownTimer >= _Delai)
{
_IsValidate = true;
}
}
}
}
and it works.
Thanks for your time, Frenchy
There is a dynamic Rigidbody that can be launched with the mouse. But at some point, Rigidbody stops reacting to the mouse for some reason. Rigidbody's speed is 0.
To a rigidbody attached two Spring joints.
The only way to awaken the body is to disable and re-enable Spring Joints when debugging.
public class Ball : MonoBehaviour
{
private Rigidbody2D rigidbodyBall;
public SpringJoint2D[] springJoints;
private GameObject speed;
public static Ball instance = null;
#region Life Cycle
void Awake()
{
speed = GameObject.Find("Velocity");
springJoints = GetComponents<SpringJoint2D>();
rigidbodyBall = GetComponent<Rigidbody2D>();
gameManager = GameObject.Find("GameManager").GetComponent<GameManager>();
}
private bool clickedOn = false;
void Update()
{
if (clickedOn)
{
Dragging();
UIManager.instance.pauseButton.SetActive(false);
UIManager.instance.totalScoreUI.gameObject.SetActive(false);
}
else
{
UIManager.instance.pauseButton.SetActive(true);
UIManager.instance.totalScoreUI.gameObject.SetActive(true);
}
}
#endregion
#region Launcher
#region Mouse
void OnMouseDown()
{
SpringJointDeactivate();
clickedOn = true;
}
void OnMouseUp()
{
SpringJointActivate();
clickedOn = false;
SetKinematicState(false);
Invoke("SpringJointDeactivate", 0.1f);
}
void Dragging()
{
Vector3 mouseWorldPointStart = transform.position;
Vector3 mouseWorldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mouseWorldPoint.z = 0f;
if (Boundary.ballInBoundary)
{
transform.position = mouseWorldPoint;
float diffX = mouseWorldPoint.x - mouseWorldPointStart.x;
//TODO
for (int i = 0; i < springJoints.Length; i++)
{
springJoints[i].connectedAnchor = new Vector2(springJoints[i].connectedAnchor.x + diffX, springJoints[i].connectedAnchor.y);
}
}
else
{
Debug.Log("Another situation!");
Debug.Log(Boundary.ballInBoundary);
}
}
#endregion
public void SpringJointActivate()
{
foreach (SpringJoint2D joint in springJoints)
{
joint.enabled = true;
}
}
public void SpringJointDeactivate()
{
foreach (SpringJoint2D joint in springJoints)
{
joint.enabled = false;
}
}
public Vector3[] GetSpringJointsConnectedAnchorCoord()
{
Vector3[] springJointsCoord = new[] { Vector3.zero, Vector3.zero };
for (int i = 0; i < springJoints.Length; i++)
{
springJointsCoord[i] = springJoints[i].connectedAnchor;
}
return springJointsCoord;
}
#endregion
public void SetKinematicState(bool kinematicState)
{
rigidbodyBall.isKinematic = kinematicState;
}
}
What is the reason for this? How can this be corrected?
Replaced OnMouseDown() with Input.GetMouseButtonDown(0) and everything worked out.
void Update()
{
if (Input.GetMouseButtonDown(0))
{
SpringJointDeactivate();
clickedOn = true;
}
if (Input.GetMouseButtonUp(0))
{
SpringJointActivate();
clickedOn = false;
SetKinematicState(false);
Invoke("SpringJointDeactivate", 0.1f);
}
}
The value of my HP bar drops when my runner collides an obstacle. Of course, Value of HP drop nomally, but Image of HP bar does not change. Why do I get an error?
public class CsRunner : MonoBehaviour
{
public Vector2 jumpVelocity;
public float _hp = 100f;
public float _curHP;
bool isJump;
public Image _hpValue;
bool collision_box;
// Use this for initialization
void Start()
{
_hpValue = GameObject.Find("HPbar").GetComponent<Image>();
_curHP = _hp;
}
// Update is called once per frame
void Update()
{
_hpValue.fillAmount = _curHP / _hp;
if (Input.GetKeyDown(KeyCode.Space) && isJump)
{
isJump = false;
transform.GetComponent<Rigidbody2D>().AddForce(jumpVelocity/2, ForceMode2D.Impulse);
}
if ((Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButtonDown(0)) && collision_box)
{
isJump = true;
transform.GetComponent<Rigidbody2D>().AddForce(jumpVelocity, ForceMode2D.Impulse);
}
else
{
GetComponent<Animator>().SetTrigger("Run");
}
}
void OnTriggerEnter2D(Collider2D coll)
{
if (coll.transform.tag == "Enemy")
{
_curHP--;
_hpValue.fillAmount = _curHP / _hp;
}
}
}
Here is a screenshot of my scene :
Thank you !