Well to make it simple the attacking animation (the animator has int parameter that takes control of the attacking animation when it is set to 4 ) does not work even if the int change to 4.
I used the same code in another object and it works perfectly.
The screenshot below shows animator control and the transmissions
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace UnityStandardAssets.Characters.FirstPerson
{
[RequireComponent(typeof (CharacterController))]
public class BOSSATTACKS : MonoBehaviour {
public GameObject prefabProjectil;
private GameObject projectil;
public Vector3 offset;
public ParticleSystem tp;
public ParticleSystem fire;
public float timeBetweenFB = 20f;
public float timeBetweenAttacks = 10f;
public float timeBetweenTp = 30f;
public int attackDamage = 10;
public Animator anim;
public GameObject boss;
GameObject player;
PlayerHealth playerHealth;
bool playerInRange;
float timer;
void Awake ()
{
player = GameObject.FindGameObjectWithTag ("Player");
playerHealth = player.GetComponent <PlayerHealth> ();
}
void OnTriggerEnter (Collider other)
{
if(other.gameObject == player)
{
playerInRange = true;
}
}
void OnTriggerExit (Collider other)
{
if(other.gameObject == player)
{
playerInRange = false;
}
}
void Update ()
{
timer += Time.deltaTime;
if (timer >= timeBetweenAttacks && playerInRange)
{
StartCoroutine (Attack ());
}
if (timer >= timeBetweenTp && playerInRange == false)
{
StartCoroutine (tp1 ());
}
}
IEnumerator tp1()
{ timer = 0f;
anim.SetInteger ("atk", 2);
tp.Play ();
yield return new WaitForSeconds(2);
boss.transform.position = player.transform.position - offset;
anim.SetInteger ("atk", 3);
}
IEnumerator Attack ()
{
timer = 0f;
if (playerHealth.currentHealth > 0) {
anim.SetInteger ("atk", 4);
yield return new WaitForSeconds (2);
playerHealth.TakeDamage (attackDamage);
anim.SetInteger ("atk", 3);
}
}
}
}
Related
Here's my code for player movement. I have set up walking around and I am now Trying to change the sprite animation when walking in different directions. Everything was working fine but when I tried to change the sprite for walking up the sprite gets stuck in a loop and doesn't idle.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public Animator Animator;
[SerializeField] private float speed = 1f;
private Rigidbody2D body;
private Vector2 axisMovement;
// Start is called before the first frame update
void Start()
{
body = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
axisMovement.x = Input.GetAxisRaw("Horizontal");
axisMovement.y = Input.GetAxisRaw("Vertical");
Animator.SetFloat("Speed", Mathf.Abs(axisMovement.x));
if (Input.GetKey(KeyCode.W))
{
Animator.SetBool("isforward", true);
}
if (Input.GetKey(KeyCode.A))
{
Animator.SetBool("isforward", false);
}
if (Input.GetKey(KeyCode.S))
{
Animator.SetBool("isforward", false);
}
if (Input.GetKey(KeyCode.D))
{
Animator.SetBool("isforward", false);
}
}
private void FixedUpdate()
{
Move();
}
private void Move()
{
body.velocity = axisMovement.normalized * speed;
CheckForFlipping();
}
private void CheckForFlipping()
{
bool movingLeft = axisMovement.x < 0;
bool movingRight = axisMovement.x > 0;
if (movingLeft)
{
transform.localScale = new Vector3(-1f, transform.localScale.y);
}
if (movingRight)
{
transform.localScale = new Vector3(1f, transform.localScale.y);
}
}
}
I also tried doing Animator.SetFloat("Speed", Mathf.Abs(axisMovement.x)); but switch it with axisMovement.y but that stops all the animations moving left and right stop working. 😢
I've figured it out. here's the updated code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public Animator Animator;
[SerializeField] private float speed = 1f;
private Rigidbody2D body;
private Vector2 axisMovement;
// Start is called before the first frame update
void Start()
{
body = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
axisMovement.x = Input.GetAxisRaw("Horizontal");
axisMovement.y = Input.GetAxisRaw("Vertical");
Animator.SetFloat("Speed", Mathf.Abs(axisMovement.x + axisMovement.y));
if (Input.GetKey(KeyCode.W))
{
Animator.SetBool("isforward", true);
} else {
Animator.SetBool("isforward", false);
}
// if (Input.GetKey(KeyCode.A))
// {
// Animator.SetBool("isforward", false);
// }
// if (Input.GetKey(KeyCode.S))
// {
// Animator.SetBool("isforward", false);
// }
// if (Input.GetKey(KeyCode.D))
// {
// Animator.SetBool("isforward", false);
// }
}
private void FixedUpdate()
{
Move();
}
private void Move()
{
body.velocity = axisMovement.normalized * speed;
CheckForFlipping();
}
private void CheckForFlipping()
{
bool movingLeft = axisMovement.x < 0;
bool movingRight = axisMovement.x > 0;
if (movingLeft)
{
transform.localScale = new Vector3(-1f, transform.localScale.y);
}
if (movingRight)
{
transform.localScale = new Vector3(1f, transform.localScale.y);
}
}
}
I'm working on a platformer game, and I instantiate my character after he gets hit by an enemy object. The problem is, my character is instantiating twice. Here's my code.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class PlayerMove : MonoBehaviour
{
public GameObject player;
private Rigidbody2D rb;
private SpriteRenderer sprite;
private BoxCollider2D coll;
private Animator anim;
public float Speed;
public float JumpForce;
private float dirX = 0f;
private float fJumpPressedRemember = 0f;
private float fJumpPressedRememberTime = 0.2f;
[SerializeField] private LayerMask jumpableGround;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
sprite = GetComponent<SpriteRenderer>();
coll = GetComponent<BoxCollider2D>();
}
// Update is called once per frame
void Update()
{
dirX = Input.GetAxisRaw("Horizontal");
rb.velocity = new Vector2(dirX * Speed, rb.velocity.y);
fJumpPressedRemember -= Time.deltaTime;
if (Input.GetButtonDown("Jump"))
{
fJumpPressedRemember = fJumpPressedRememberTime;
}
if ((fJumpPressedRemember > 0) && isGrounded())
{
fJumpPressedRemember = 0;
rb.velocity = new Vector2(rb.velocity.x, JumpForce);
}
UpdateAnimation();
}
private bool isGrounded()
{
return Physics2D.BoxCast(coll.bounds.center, coll.bounds.size, 0f, Vector2.down, .1f, jumpableGround);
}
void OnCollisionEnter2D(Collision2D spikeCol)
{
if (spikeCol.gameObject.tag.Equals("DamageDealer") == true)
{
Instantiate(player, new Vector3(-10, 1, 0), Quaternion.identity);
Destroy(player);
}
if (spikeCol.gameObject.tag.Equals("End") == true)
{
SceneManager.LoadScene("Level2", LoadSceneMode.Single);
}
if (spikeCol.gameObject.tag.Equals("End2") == true)
{
SceneManager.LoadScene("Level1", LoadSceneMode.Single);
}
}
private void UpdateAnimation()
{
if (dirX > 0f)
{
anim.SetBool("running", true);
sprite.flipX = false;
}
else if (dirX < 0f)
{
anim.SetBool("running", true);
sprite.flipX = true;
}
else
{
anim.SetBool("running", false);
}
}
}
It's supposed to instantiate once after dying. I don't know what's happening, but it only started after I added animation code, so I think that's the issue. Thanks to anyone who can help!
OnCollisionEnter2D is called twice.
Reasons why this can be described here: Why is OnCollisionEnter getting called twice?
You can add instantiate method double call check, like this:
private bool isInited;
void OnCollisionEnter2D(Collision2D spikeCol)
{
if (spikeCol.gameObject.tag.Equals("DamageDealer") == true)
{
if (isInited)
{
return;
}
isInited = true;
Instantiate(player, new Vector3(-10, 1, 0), Quaternion.identity);
Destroy(player);
}
...
}
When creating the game, I came across the problem that after adding animation to the player's code in the play mode, he stopped moving.
I did everything as usual, went into the animator, made an animation, and then set up and added everything necessary to the code in the animator, but after that the player stopped moving although before that everything was fine.
Help me, I hope it's not difficult.
Here is the code
using System.Collections;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[Header("Controlled player")]
public Rigidbody2D rb;
[Header("Tinctures of movement")]
public float PSpeed = 1f;
public float jumpForce = 1f;
[Header("Variable Reduction parameters")]
public float LowingPSPeed;
public float FormedPSpeed;
[Header("Traffic Statuses")]
public bool Move;
public bool Jump;
[Header("")]
[Header("Checking the ground under the player")]
public bool OnGround;
private bool doJump = false;
private bool GOright = false;
private bool GOleft = false;
[Header("Ground Check Settings")]
private float groundRadius = 0.3f;
public Transform groundCheck;
public LayerMask groundMask;
private Animator anim;
void Math()
{
FormedPSpeed = PSpeed / LowingPSPeed;
}
void Start()
{
anim = GetComponent<Animator>();
}
void Update()
{
Math();
if (Input.GetKeyDown(KeyCode.Space))
{
doJump = true;
}
if (Input.GetKey("d"))
{
GOright = true;
}else
{
GOright = false;
}
if (Input.GetKey("a"))
{
GOleft = true;
}
else
{
GOleft = false;
}
}
void FixedUpdate()
{
OnGround = Physics2D.OverlapCircle(groundCheck.position, groundRadius, groundMask);
if (GOright && Move)
{
transform.position += new Vector3(FormedPSpeed, 0, 0);
GetComponent<SpriteRenderer>().flipX = false;
}
if (GOleft && Move)
{
transform.position += new Vector3(-(FormedPSpeed), 0, 0);
GetComponent<SpriteRenderer>().flipX = true;
}
if (doJump && Jump && OnGround)
{
rb.AddForce(new Vector2(0, (jumpForce * 10)));
anim.SetTrigger("takeOf");
doJump = false;
}
if (OnGround)
{
anim.SetBool("isJump", false);
}else
{
anim.SetBool("isJump", true);
}
if (!GOleft && !GOright)
{
anim.SetBool("isRun", false);
}else
{
anim.SetBool("isRun", true);
}
}
I don't understand why this is happening
So as previously said I need the bullet to follow the enemy. I'm making a 2d Game and just can't figure out how. I'll appreciate it if someone could help me. Here are my scripts.
Bullet Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerFire : MonoBehaviour
{
float moveSpeed = 25f;
Rigidbody2D rb;
Monster target;
Vector2 moveDirection;
public float firespeed;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
transform.Translate(Vector2.right * firespeed * Time.deltaTime, Space.Self);
}
private void OnCollisionEnter2D(Collision2D collision)
{
Debug.Log(collision.transform.name);
Destroy(gameObject);
}
}
Enemy script
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Monster : MonoBehaviour {
[SerializeField]
GameObject bullet;
float fireRate;
float nextFire;
public Image BosshealthBar;
public float BosshealthAmount = 100;
public GameObject effect;
// Use this for initialization
void Start () {
fireRate = 1f;
nextFire = Time.time;
}
// Update is called once per frame
void Update () {
CheckIfTimeToFire ();
if (BosshealthAmount <= 0)
{
Destroy(gameObject);
}
}
void CheckIfTimeToFire()
{
if (Time.time > nextFire) {
Instantiate (bullet, transform.position, Quaternion.identity);
nextFire = Time.time + fireRate;
}
}
public void TakeDamage(float Damage)
{
BosshealthAmount -= Damage;
BosshealthBar.fillAmount = BosshealthAmount / 100;
}
public void Healing(float healPoints)
{
BosshealthAmount += healPoints;
BosshealthAmount = Mathf.Clamp(BosshealthAmount, 0, 100);
BosshealthBar.fillAmount = BosshealthAmount / 100;
}
void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.tag.Equals("BulletPlayer"))
{
TakeDamage(10);
Instantiate(effect, transform.position, Quaternion.identity);
}
}
}
Something like this may help u
Vector3 direction = Target.position - Bullet.position;
float distance = direction.magnitude;
float TargetSpeed = 5
Vector3 Force = direction.normalized * ForceMagnitude;
Bullet.AddForce(Force);
But you will need to add it in yourself since i can't tell how your code speceficly works
Hello i am making a 2d game and I have a player that needs to collide with 2 objects. First object gives him more health and has the tag " power up " and works but the second that has the tag " Hurt" it's not working . What I should change in the script ? Here it's the script for " PowerUp" and here it's the script of the player.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
public class PowerUpDetector : MonoBehaviourPun
{
// reference this via the Inspector
[SerializeField] private Character healthbar;
[SerializeField] private Character health;
private void Awake()
{
if (!healthbar) healthbar = GetComponent<Character>();
}
private void OnTriggerEnter2D(Collider2D other)
{
// or whatever tag your powerups have
if (!other.CompareTag("PowerUp"))
{
Debug.LogWarning($"Registered a collision but with wrong tag: {other.tag}", this);
return;
}
var powerup = other.GetComponent<PowerUp>();
if (!powerup)
{
Debug.LogError($"Object {other.name} is tagged PowerUp but has no PowerUp component attached", this);
return;
}
Debug.Log("Found powerup, pick it up!", this);
powerup.Pickup(healthbar);
if (!other.CompareTag("Hurt"))
{
if (photonView.IsMine)
{
photonView.RPC("Damage", RpcTarget.All);
}
}
}
[PunRPC]
void Damage()
{
health -= 20;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;
using Photon.Pun;
using Photon.Realtime;
using Photon;
using UnityEngine.UI;
public class Character : MonoBehaviourPun,IPunObservable
{
Rigidbody2D rb;
float dirX;
[SerializeField]
float moveSpeed = 5f, jumpForce = 400f, bulletSpeed = 500f;
[SerializeField] private float health = 100;
[SerializeField] private Slider slider;
[SerializeField] private Gradient gradient;
[SerializeField] private Image fill;
Vector3 localScale;
public Transform barrel;
public Rigidbody2D bullet;
// Use this for initialization
void Start()
{
localScale = transform.localScale;
rb = GetComponent<Rigidbody2D>();
if (photonView.IsMine)
{
}
else
{
}
}
public float Health
{
get { return health; }
set
{
health = value;
slider.value = health;
fill.color = gradient.Evaluate(slider.normalizedValue);
}
}
private void OnCollisionEntered2D(Collision2D col)
{
if( col.gameObject.CompareTag ("Hurt"))
{
if (photonView.IsMine)
{
photonView.RPC("Damage", RpcTarget.All);
}
}
}
[PunRPC]
void Damage()
{
health -= 20;
}
// Update is called once per frame
void Update()
{
if (photonView.IsMine)
{
dirX = CrossPlatformInputManager.GetAxis("Horizontal");
if (dirX != 0)
{
barrel.up = Vector3.right * Mathf.Sign(dirX);
}
if (CrossPlatformInputManager.GetButtonDown("Jump"))
Jump();
if (CrossPlatformInputManager.GetButtonDown("Fire1"))
Fire();
}
else
{
}
}
void FixedUpdate()
{
if (photonView.IsMine)
{
rb.velocity = new Vector2(dirX * moveSpeed, rb.velocity.y);
}
}
void Jump()
{
if (photonView.IsMine)
{
if (rb.velocity.y == 0)
rb.AddForce(Vector2.up * jumpForce);
}
}
void Fire()
{
if (photonView.IsMine)
{
var firedBullet = Instantiate(bullet, barrel.position, barrel.rotation);
firedBullet.AddForce(barrel.up * bulletSpeed);
}
}
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
if (stream.IsWriting)
{
stream.SendNext(health);
}else if (stream.IsReading)
{
health = (float)stream.ReceiveNext();
}
}
public void SetMaxHealth(int value)
{
if (photonView.IsMine)
{
slider.maxValue = value;
// The property handles the rest anyway
Health = value;
}
}
}
I have an error in the "Power Up Detector" at health -= 20 (operator -= can't be applied ) to operands type "Character" and " int" .
I think you will have to use health.Health. Your variable health refers to the Character class. As you want to change the health, you would have to use the property of that class instead. So try:
health.Health -= 20;
I would recommend to rename the health variable to something else related to the Character class though.