Forum begins after the advertisement:


[Part 7] My Shade cannot function

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 7] My Shade cannot function

Viewing 12 posts - 1 through 12 (of 12 total)
  • Author
    Posts
  • #13801
    Elvin Sim
    Participant

    Hi, sorry for disturbing but my shade is not function, in the video, it didn’t show how the shade settings and so I get some error, like when I death the respawn button and the shade don’t exist.

    #13802
    #13804
    Elvin Sim
    Participant

    using Microsoft.Unity.VisualStudio.Editor;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UIElements;
    using UnityEngine.UI;
    using Cinemachine;

    public class PlayerController : MonoBehaviour
    {
    [Header(“Horizontal Movement Settings:”)]
    [SerializeField] private float walkSpeed = 1;
    [Space(5)]

    [Header(“Vertical Movement Settings:”)]
    [SerializeField] private float jumpForce = 45f;

    private int jumpBufferCounter = 0;
    [SerializeField] private int jumpBufferFrames;

    private float coyoteTimeCounter = 0;
    [SerializeField] private float coyoteTime;

    private int airJumpCounter = 0;
    [SerializeField] private int maxAirJumps;

    private float gravity;
    [Space(5)]

    [Header(“Ground Check Settings:”)]
    [SerializeField] private Transform groundCheckPoint;
    [SerializeField] private float groundCheckY = 0.2f;
    [SerializeField] private float groundCheckX = 0.5f;
    [SerializeField] private LayerMask whatIsGround;
    [Space(5)]

    [Header(“Dash Settings:”)]
    [SerializeField] private float dashSpeed;
    [SerializeField] private float dashTime;
    [SerializeField] private float dashCooldown;
    [SerializeField] GameObject dashEffect;
    private bool canDash = true;
    private bool dashed;
    [Space(5)]

    [Header(“Attack Settings:”)]
    [SerializeField] private Transform SideAttackTransform;
    [SerializeField] private Vector2 SideAttackArea;

    [SerializeField] private Transform UpAttackTransform;
    [SerializeField] private Vector2 UpAttackArea;

    [SerializeField] private Transform DownAttackTransform;
    [SerializeField] private Vector2 DownAttackArea;

    [SerializeField] private LayerMask attackableLayer;

    private float timeBetweenAttack, timeSinceAttack;

    [SerializeField] private float damage;

    [SerializeField] private GameObject slashEffect;

    bool restoreTime;
    float restoreTimeSpeed;
    [Space(5)]

    [Header(“Recoil Settings:”)]
    [SerializeField] private int recoilXSteps = 5;
    [SerializeField] private int recoilYSteps = 5;

    [SerializeField] private float recoilXSpeed = 100;
    [SerializeField] private float recoilYSpeed = 100;

    private int stepsXRecoiled, stepsYRecoiled;
    [Space(5)]

    [Header(“Health Settings:”)]
    public int health;
    public int maxHealth;
    [SerializeField] GameObject bloodSpurt;
    [SerializeField] float hitFlashSpeed;
    public delegate void OnHealthChangedDelegate();
    [HideInInspector] public OnHealthChangedDelegate onHealthChangedCallback;

    float healTimer;
    [SerializeField] float timeToHeal;
    [Space(5)]

    [Header(“Mana Settings:”)]
    [SerializeField] UnityEngine.UI.Image manaStorage;
    [SerializeField] float mana;
    [SerializeField] float manaDrainSpeed;
    [SerializeField] float manaGain;
    bool halfMana;
    [Space(5)]

    [Header(“Spell Settings:”)]
    [SerializeField] float manaSpellCost = 0.3f;
    [SerializeField] float timeBetweenCast = 0.5f;
    [SerializeField] float spellDamage; //upspellexplosion and downspellfireball
    [SerializeField] float downSpellForce; //desolate dive only
    //spell cast objects
    [SerializeField] GameObject sideSpellFireball;
    [SerializeField] GameObject upSpellExplosion;
    [SerializeField] GameObject downSpellFireball;
    float timeSinceCast;
    float castOrHealtimer;
    [Space(5)]

    [Header(“Camera Stuff”)]
    [SerializeField] private float playerFallSpeedThreshold = -5;

    [HideInInspector] public PlayerStateList pState;
    [HideInInspector] public Rigidbody2D rb;
    private Animator anim;
    private SpriteRenderer sr;

    //Input Variables
    private float xAxis, yAxis;
    private bool attack = false;
    private bool canFlash = true;

    public static PlayerController Instance;

    private void Awake()
    {
    if (Instance != null && Instance != this)
    {
    Destroy(gameObject);
    }
    else
    {
    Instance = this;
    }
    DontDestroyOnLoad(gameObject);
    }

    // Start is called before the first frame update
    void Start()
    {
    pState = GetComponent<PlayerStateList>();

    rb = GetComponent<Rigidbody2D>();
    sr = GetComponent<SpriteRenderer>();

    anim = GetComponent<Animator>();

    gravity = rb.gravityScale;

    Mana = mana;
    manaStorage.fillAmount = Mana;

    Health = maxHealth;
    }

    private void OnDrawGizmos()
    {
    Gizmos.color = Color.red;
    Gizmos.DrawWireCube(SideAttackTransform.position, SideAttackArea);
    Gizmos.DrawWireCube(UpAttackTransform.position, UpAttackArea);
    Gizmos.DrawWireCube(DownAttackTransform.position, DownAttackArea);
    }

    // Update is called once per frame
    void Update()
    {
    if (pState.cutscene) return;
    if (pState.alive)
    {
    GetInputs();
    }

    UpdateJumpVariables();
    UpdateCameraYDampForPlayerFall();
    RestoreTimeScale();
    Heal();

    if (pState.dashing || pState.healing) return;
    if (pState.alive)
    {
    Flip();
    Move();
    Jump();
    StartDash();
    Attack();
    CastSpell();
    }
    FlashWhileInvincible();
    }

    private void OnTriggerEnter2D(Collider2D _other) //for up and down spell cast
    {
    if(_other.GetComponent<Enemy>() != null && pState.casting)
    {
    _other.GetComponent<Enemy>().EnemyHit(spellDamage, (_other.transform.position – transform.position).normalized, -recoilYSpeed);
    }
    }

    private void FixedUpdate()
    {
    if (pState.cutscene) return;

    if (pState.dashing || pState.healing) return;
    Recoil();
    }

    void GetInputs()
    {
    xAxis = Input.GetAxisRaw(“Horizontal”);
    yAxis = Input.GetAxisRaw(“Vertical”);
    attack = Input.GetButtonDown(“Attack”);

    if (Input.GetButton(“Cast/Heal”))
    {
    castOrHealtimer += Time.deltaTime;
    }

    }

    void Flip()
    {
    if (xAxis < 0)
    {
    transform.localScale = new Vector2(-1, transform.localScale.y);
    pState.lookingRight = false;
    }
    else if (xAxis > 0)
    {
    transform.localScale = new Vector2(1, transform.localScale.y);
    pState.lookingRight = true;
    }
    }

    private void Move()
    {
    rb.velocity = new Vector2(walkSpeed * xAxis, rb.velocity.y);
    anim.SetBool(“Walking”, rb.velocity.x != 0 && Grounded());
    }

    void UpdateCameraYDampForPlayerFall()
    {
    //if falling past a certain speed threshold
    if(rb.velocity.y < playerFallSpeedThreshold && !CameraManager.Instance.isLerpingYDamping && !CameraManager.Instance.hasLerpedYDamping)
    {
    StartCoroutine(CameraManager.Instance.LerpYDamping(true));
    }
    //if standing still or moving up
    if(rb.velocity.y >= 0 && !CameraManager.Instance.isLerpingYDamping && CameraManager.Instance.hasLerpedYDamping)
    {
    //reset camera function
    CameraManager.Instance.hasLerpedYDamping = false;
    StartCoroutine(CameraManager.Instance.LerpYDamping(false));
    }
    }

    void StartDash()
    {
    if (Input.GetButtonDown(“Dash”) && canDash && !dashed)
    {
    StartCoroutine(Dash());
    dashed = true;
    }

    if (Grounded())
    {
    dashed = false;
    }
    }

    IEnumerator Dash()
    {
    canDash = false;
    pState.dashing = true;
    anim.SetTrigger(“Dashing”);
    rb.gravityScale = 0;
    int _dir = pState.lookingRight ? 1 : -1;
    rb.velocity = new Vector2(_dir * dashSpeed, 0);
    if (Grounded()) Instantiate(dashEffect, transform);
    yield return new WaitForSeconds(dashTime);
    rb.gravityScale = gravity;
    pState.dashing = false;
    yield return new WaitForSeconds(dashCooldown);
    canDash = true;
    }

    public IEnumerator WalkIntoNewScene(Vector2 _exitDir, float _delay)
    {
    //If exit direction is upwards
    if(_exitDir.y != 0)
    {
    rb.velocity = jumpForce * _exitDir;
    }

    //If exit direction requires horizontal movement
    if(_exitDir.x != 0)
    {
    xAxis = _exitDir.x > 0 ? 1 : -1;

    Move();
    }

    Flip();
    yield return new WaitForSeconds(_delay);
    pState.cutscene = false;
    }

    void Attack()
    {
    timeSinceAttack += Time.deltaTime;
    if(attack && timeSinceAttack >= timeBetweenAttack)
    {
    timeSinceAttack = 0;
    anim.SetTrigger(“Attacking”);

    if(yAxis == 0 || yAxis < 0 && Grounded())
    {
    int _recoilLeftOrRight = pState.lookingRight ? 1 : -1;

    Hit(SideAttackTransform, SideAttackArea, ref pState.recoilingX, Vector2.right * _recoilLeftOrRight, recoilXSpeed);
    Instantiate(slashEffect, SideAttackTransform);
    }
    else if(yAxis > 0)
    {
    Hit(UpAttackTransform, UpAttackArea, ref pState.recoilingY, Vector2.up, recoilYSpeed);
    SlashEffectAtAngle(slashEffect, 80, UpAttackTransform);
    }
    else if (yAxis < 0 && !Grounded())
    {
    Hit(DownAttackTransform, DownAttackArea, ref pState.recoilingY, Vector2.down, recoilYSpeed);
    SlashEffectAtAngle(slashEffect, -90, DownAttackTransform);
    }
    }
    }

    void Hit(Transform _attackTransform, Vector2 _attackArea, ref bool _recoilBool, Vector2 _recoilDir, float _recoilStrength)
    {
    Collider2D[] objectsToHit = Physics2D.OverlapBoxAll(_attackTransform.position, _attackArea, 0, attackableLayer);

    if(objectsToHit.Length > 0)
    {
    _recoilBool = true;
    }
    for(int i = 0; i < objectsToHit.Length; i++)
    {
    if (objectsToHit[i].GetComponent<Enemy>() != null)
    {
    objectsToHit[i].GetComponent<Enemy>().EnemyHit(damage, _recoilDir, _recoilStrength);

    if (objectsToHit[i].CompareTag(“Enemy”))
    {
    Mana += manaGain;
    }
    }
    }
    }

    void SlashEffectAtAngle(GameObject _slashEffect, int _effectAngle, Transform _attackTransform)
    {
    _slashEffect = Instantiate(_slashEffect, _attackTransform);
    _slashEffect.transform.eulerAngles = new Vector3(0, 0, _effectAngle);
    _slashEffect.transform.localScale = new Vector2(transform.localScale.x, transform.localScale.y);
    }

    void Recoil()
    {
    if(pState.recoilingX)
    {
    if(pState.lookingRight)
    {
    rb.velocity = new Vector2(-recoilXSpeed, 0);
    }
    else
    {
    rb.velocity = new Vector2(recoilXSpeed, 0);
    }
    }

    if (pState.recoilingY)
    {
    rb.gravityScale = 0;
    if (yAxis < 0)
    {
    rb.velocity = new Vector2(rb.velocity.x, recoilYSpeed);
    }
    else
    {
    rb.velocity = new Vector2(rb.velocity.x, -recoilYSpeed);
    }
    airJumpCounter = 0;
    }
    else
    {
    rb.gravityScale = gravity;
    }

    //stop recoil
    if(pState.recoilingX && stepsXRecoiled < recoilXSteps)
    {
    stepsXRecoiled++;
    }
    else
    {
    StopRecoilX();
    }
    if (pState.recoilingY && stepsYRecoiled < recoilYSteps)
    {
    stepsYRecoiled++;
    }
    else
    {
    StopRecoilY();
    }

    if (Grounded())
    {
    StopRecoilY();
    }
    }

    void StopRecoilX()
    {
    stepsXRecoiled = 0;
    pState.recoilingX = false;
    }

    void StopRecoilY()
    {
    stepsYRecoiled = 0;
    pState.recoilingY = false;
    }

    public void TakeDamage(float _damage)
    {
    if (pState.alive)
    {
    Health -= Mathf.RoundToInt(_damage);
    if(Health <= 0)
    {
    Health = 0;
    StartCoroutine(Death());
    }
    else
    {
    StartCoroutine(StopTakingDamage());
    }

    }

    }

    IEnumerator StopTakingDamage()
    {
    pState.invincible = true;
    GameObject _bloodSpurtParticles = Instantiate(bloodSpurt, transform.position, Quaternion.identity);
    Destroy(_bloodSpurtParticles, 1.5f);
    anim.SetTrigger(“TakeDamage”);
    yield return new WaitForSeconds(1f);
    pState.invincible = false;
    }

    IEnumerator Flash()
    {
    sr.enabled = !sr.enabled;
    canFlash = false;
    yield return new WaitForSeconds(0.2f);
    canFlash = true;
    }

    void FlashWhileInvincible()
    {
    if(pState.invincible)
    {
    if(Time.timeScale > 0.2 && canFlash)
    {
    StartCoroutine(Flash());
    }
    }
    else
    {
    sr.enabled = true;
    }
    }

    void RestoreTimeScale()
    {
    if (restoreTime)
    {
    if(Time.timeScale < 1)
    {
    Time.timeScale += Time.deltaTime * restoreTimeSpeed;
    }
    else
    {
    Time.timeScale = 1;
    restoreTime = false;
    }
    }
    }

    public void HitStopTime(float _newTimeScale, int _restoreSpeed, float _delay)
    {
    restoreTimeSpeed = _restoreSpeed;
    Time.timeScale = _newTimeScale;

    if(_delay > 0)
    {
    StopCoroutine(StartTimeAgain(_delay));
    StartCoroutine(StartTimeAgain(_delay));
    }
    else
    {
    restoreTime = true;
    }
    }

    IEnumerator StartTimeAgain(float _delay)
    {
    restoreTime = true;
    yield return new WaitForSeconds(_delay);
    }

    IEnumerator Death()
    {
    pState.alive = false;
    Time.timeScale = 1f;
    GameObject _bloodSpurtParticles = Instantiate(bloodSpurt, transform.position, Quaternion.identity);
    Destroy(_bloodSpurtParticles, 1.5f);
    anim.SetTrigger(“Death”);

    yield return new WaitForSeconds(0.9f);
    StartCoroutine(UIManager.Instance.ActivateDeathScreen());

    yield return new WaitForSeconds(0.9f);
    Instantiate(GameManager.Instance.shade, transform.position, Quaternion.identity);
    }

    public void Respawned()
    {
    if(!pState.alive)
    {
    pState.alive = true;
    halfMana = true;
    UIManager.Instance.SwitchMana(UIManager.ManaState.HalfMana);
    Mana = 0;
    Health = maxHealth;
    anim.Play(“player_idle”);
    }
    }

    public void RestoreMana()
    {
    halfMana = false;
    UIManager.Instance.SwitchMana(UIManager.ManaState.FullMana);
    }

    public int Health
    {
    get { return health; }
    set
    {
    if (health != value)
    {
    health = Mathf.Clamp(value, 0, maxHealth);

    if(onHealthChangedCallback != null)
    {
    onHealthChangedCallback.Invoke();
    }
    }
    }
    }

    void Heal()
    {
    if(Input.GetButton(“Cast/Heal”) && castOrHealtimer > 0.05f && Health < maxHealth && Mana > 0 && !pState.jumping && !pState.dashing)
    {
    pState.healing = true;
    anim.SetBool(“Healing”, true);

    //healing
    healTimer += Time.deltaTime;
    if(healTimer >= timeToHeal)
    {
    Health++;
    healTimer = 0;
    }

    //drain mana
    Mana -= Time.deltaTime * manaDrainSpeed;
    }
    else
    {
    pState.healing = false;
    anim.SetBool(“Healing”, false);
    healTimer = 0;
    }
    }

    float Mana
    {
    get { return mana; }
    set
    {
    //if mana stats change
    if(mana != value)
    {
    if (!halfMana)
    {
    mana = Mathf.Clamp(value, 0, 1);
    }
    else
    {
    mana = Mathf.Clamp(value, 0, 0.5f);
    }

    manaStorage.fillAmount = Mana;
    }
    }
    }

    void CastSpell()
    {
    if(Input.GetButtonUp(“Cast/Heal”) && castOrHealtimer <= 0.1f && timeSinceCast >= timeBetweenCast && Mana >= manaSpellCost)
    {
    pState.casting = true;
    timeSinceCast = 0;
    StartCoroutine(CastCoroutine());
    }
    else
    {
    timeSinceCast += Time.deltaTime;
    }

    if (!Input.GetButton(“Cast/Heal”))
    {
    castOrHealtimer = 0;
    }

    if (Grounded())
    {
    //disable downspell if on the ground
    downSpellFireball.SetActive(false);
    }
    //if down spell is active, force player down until grounded
    if(downSpellFireball.activeInHierarchy)
    {
    rb.velocity += downSpellForce * Vector2.down;
    }
    }

    IEnumerator CastCoroutine()
    {
    anim.SetBool(“Casting”, true);
    yield return new WaitForSeconds(0.15f);

    //side cast
    if(yAxis == 0 || (yAxis < 0 && Grounded()))
    {
    GameObject _fireBall = Instantiate(sideSpellFireball, SideAttackTransform.position, Quaternion.identity);

    //flip fireball
    if (pState.lookingRight)
    {
    _fireBall.transform.eulerAngles = Vector3.zero; //if facing right, fireball continues as per normal
    }
    else
    {
    _fireBall.transform.eulerAngles = new Vector2(_fireBall.transform.eulerAngles.x, 180);
    //if not facing right, rotate the fireball 180 deg
    }
    pState.recoilingX = true;
    }

    //up cast
    else if(yAxis > 0)
    {
    Instantiate(upSpellExplosion, transform);
    rb.velocity = Vector2.zero;
    }

    //down cast
    else if(yAxis < 0 && !Grounded())
    {
    downSpellFireball.SetActive(true);
    }

    Mana -= manaSpellCost;
    yield return new WaitForSeconds(0.35f);
    anim.SetBool(“Casting”, false);
    pState.casting = false;
    }

    public bool Grounded()
    {
    if (Physics2D.Raycast(groundCheckPoint.position, Vector2.down, groundCheckY, whatIsGround)
    || Physics2D.Raycast(groundCheckPoint.position + new Vector3(groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround)
    || Physics2D.Raycast(groundCheckPoint.position + new Vector3(-groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround))
    {
    return true;
    }
    else
    {
    return false;
    }
    }

    void Jump()
    {
    if (jumpBufferCounter > 0 && coyoteTimeCounter > 0 && !pState.jumping)
    {
    rb.velocity = new Vector3(rb.velocity.x, jumpForce);

    pState.jumping = true;
    }

    if (!Grounded() && airJumpCounter < maxAirJumps && Input.GetButtonDown(“Jump”))
    {
    pState.jumping = true;

    airJumpCounter++;

    rb.velocity = new Vector3(rb.velocity.x, jumpForce);
    }

    if (Input.GetButtonUp(“Jump”) && rb.velocity.y > 3)
    {
    rb.velocity = new Vector2(rb.velocity.x, 0);

    pState.jumping = false;
    }

    anim.SetBool(“Jumping”, !Grounded());
    }

    void UpdateJumpVariables()
    {
    if (Grounded())
    {
    pState.jumping = false;
    coyoteTimeCounter = coyoteTime;
    airJumpCounter = 0;
    }
    else
    {
    coyoteTimeCounter -= Time.deltaTime;
    }

    if (Input.GetButtonDown(“Jump”))
    {
    jumpBufferCounter = jumpBufferFrames;
    }
    else
    {
    jumpBufferCounter–;
    }
    }
    }

    #13805
    Elvin Sim
    Participant

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class Shade : Enemy
    {
    [SerializeField] private float chaseDistance;
    [SerializeField] private float stunDuration;

    float timer;

    public static Shade Instance;

    private void Awake()
    {
    if(Instance != null && Instance != this)
    {
    Destroy(gameObject);
    }
    else
    {
    Instance = this;
    }
    }

    // Start is called before the first frame update
    protected override void Start()
    {
    base.Start();
    ChangeState(EnemyStates.Shade_Idle);
    }

    protected override void Update()
    {
    base.Update();
    if (!PlayerController.Instance.pState.alive)
    {
    ChangeState(EnemyStates.Shade_Idle);
    }
    }

    protected override void UpdateEnemyState()
    {
    float _dist = Vector2.Distance(transform.position, PlayerController.Instance.transform.position);

    switch (GetCurrentEnemyState)
    {
    case EnemyStates.Shade_Idle:
    if (_dist < chaseDistance)
    {
    ChangeState(EnemyStates.Shade_Chase);
    }
    break;

    case EnemyStates.Shade_Chase:
    rb.MovePosition(Vector2.MoveTowards(transform.position, PlayerController.Instance.transform.position, Time.deltaTime * speed));

    Flip();
    break;

    case EnemyStates.Shade_Stunned:
    timer += Time.deltaTime;

    if (timer > stunDuration)
    {
    ChangeState(EnemyStates.Shade_Idle);
    timer = 0;
    }
    break;

    case EnemyStates.Shade_Death:
    Death(Random.Range(5, 10));
    break;
    }
    }

    public override void EnemyHit(float _damageDone, Vector2 _hitDirection, float _hitForce)
    {
    base.EnemyHit(_damageDone, _hitDirection, _hitForce);

    if (health > 0)
    {
    ChangeState(EnemyStates.Shade_Stunned);
    }
    else
    {
    ChangeState(EnemyStates.Shade_Death);
    }
    }

    protected override void Death(float _destroyTime)
    {
    rb.gravityScale = 12;
    base.Death(_destroyTime);
    }

    protected override void ChangeCurrentAnimation()
    {
    if(GetCurrentEnemyState == EnemyStates.Shade_Idle)
    {
    anim.Play(“player_idle”);
    }

    anim.SetBool(“Walking”, GetCurrentEnemyState == EnemyStates.Shade_Chase);

    if (GetCurrentEnemyState == EnemyStates.Shade_Death)
    {
    PlayerController.Instance.RestoreMana();
    anim.SetTrigger(“Death”);
    Destroy(gameObject, 0.5f);
    }
    }

    protected override void Attack()
    {
    anim.SetTrigger(“Attacking”);
    PlayerController.Instance.TakeDamage(damage);
    }

    void Flip()
    {
    sr.flipX = PlayerController.Instance.transform.position.x < transform.position.x;
    }
    }

    #13806
    Elvin Sim
    Participant

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class Enemy : MonoBehaviour
    {
    [SerializeField] protected float health;
    [SerializeField] protected float recoilLength;
    [SerializeField] protected float recoilFactor;
    [SerializeField] protected bool isRecoiling = false;

    [SerializeField] protected float speed;

    [SerializeField] protected float damage;
    [SerializeField] protected GameObject orangeBlood;

    protected float recoilTimer;
    protected Rigidbody2D rb;
    protected SpriteRenderer sr;
    protected Animator anim;

    protected enum EnemyStates
    {
    //Crawler
    Crawler_Idle,
    Crawler_Flip,

    //Bat
    Bat_Idle,
    Bat_Chase,
    Bat_Stunned,
    Bat_Death,

    //Charger
    Charger_Idle,
    Charger_Suprised,
    Charger_Charge,

    //Shade
    Shade_Idle,
    Shade_Chase,
    Shade_Stunned,
    Shade_Death
    }
    protected EnemyStates currentEnemyState;

    protected virtual EnemyStates GetCurrentEnemyState
    {
    get { return currentEnemyState; }
    set
    {
    if (currentEnemyState != value)
    {
    currentEnemyState = value;

    ChangeCurrentAnimation();
    }
    }
    }

    // Start is called before the first frame update
    protected virtual void Start()
    {
    rb = GetComponent<Rigidbody2D>();
    sr = GetComponent<SpriteRenderer>();
    anim = GetComponent<Animator>();
    }

    // Update is called once per frame
    protected virtual void Update()
    {
    if(isRecoiling)
    {
    if(recoilTimer < recoilLength)
    {
    recoilTimer += Time.deltaTime;
    }
    else
    {
    isRecoiling = false;
    recoilTimer = 0;
    }
    }
    else
    {
    UpdateEnemyState();
    }
    }

    public virtual void EnemyHit(float _damageDone, Vector2 _hitDirection, float _hitForce)
    {
    health -= _damageDone;
    if (!isRecoiling)
    {
    GameObject _orangeBlood = Instantiate(orangeBlood, transform.position, Quaternion.identity);
    Destroy(_orangeBlood, 5.5f);
    rb.velocity = _hitForce * recoilFactor * _hitDirection;
    }
    }
    protected void OnCollisionStay2D(Collision2D _other)
    {
    if (_other.gameObject.CompareTag(“Player”) && !PlayerController.Instance.pState.invincible && health > 0)
    {
    Attack();
    if(PlayerController.Instance.pState.alive)
    {
    PlayerController.Instance.HitStopTime(0, 5, 0.5f);
    }
    }
    }

    protected virtual void Death(float _destroyTime)
    {
    Destroy(gameObject, _destroyTime);
    }

    protected virtual void UpdateEnemyState() { }
    protected virtual void ChangeCurrentAnimation() { }

    protected void ChangeState(EnemyStates _newState)
    {
    GetCurrentEnemyState = _newState;
    }

    protected virtual void Attack()
    {
    PlayerController.Instance.TakeDamage(damage);
    }
    }

    #13807
    Elvin Sim
    Participant

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class GameManager : MonoBehaviour
    {
    public string transitionedFromScene;

    public Vector2 platformingRespawnPoint;
    public Vector2 respawnPoint;
    [SerializeField] Bench bench;

    public GameObject shade;

    public static GameManager Instance { get; private set; }
    private void Awake()
    {
    if(Instance != null && Instance != this)
    {
    Destroy(gameObject);
    }
    else
    {
    Instance = this;
    }
    DontDestroyOnLoad(gameObject);
    bench = FindObjectOfType<Bench>();
    }

    public void RespawnPlayer()
    {
    if(bench != null)
    {
    if (bench.interacted)
    {
    respawnPoint = bench.transform.position;
    }
    else
    {
    respawnPoint = platformingRespawnPoint;
    }
    }
    else
    {
    respawnPoint = platformingRespawnPoint;
    }

    PlayerController.Instance.transform.position = respawnPoint;

    StartCoroutine(UIManager.Instance.DeactivateDeathScreen());
    PlayerController.Instance.Respawned();
    }

    }

    #13809
    Joseph Tang
    Moderator

    Hi, can you check if your GameManager game object has the Shade Prefab assigned? In the first Imgur image you posted, the second error says that it has not been assigned yet.

    #13812
    Elvin Sim
    Participant

    IEnumerator Death()
    {
    pState.alive = false;
    Time.timeScale = 1f;
    GameObject _bloodSpurtParticles = Instantiate(bloodSpurt, transform.position, Quaternion.identity);
    Destroy(_bloodSpurtParticles, 1.5f);
    anim.SetTrigger(“Death”);

    yield return new WaitForSeconds(0.9f);
    StartCoroutine(UIManager.Instance.ActivateDeathScreen());

    yield return new WaitForSeconds(0.9f);
    Instantiate(GameManager.Instance.shade, transform.position, Quaternion.identity);
    }

    #13813
    Elvin Sim
    Participant

    public string transitionedFromScene;

    public Vector2 platformingRespawnPoint;
    public Vector2 respawnPoint;
    [SerializeField] Bench bench;

    public GameObject shade;

    #13814
    Elvin Sim
    Participant

    These is the place that keep coming error

    #13815
    Elvin Sim
    Participant

    Sorry, I have found the solution I forget to assigned my shade to the GameManager in unity

    #13816
    Joseph Tang
    Moderator

    Yes, glad you found it. When you get a bug do check all error messages as one of them had a warning for the missing assignment as well.

Viewing 12 posts - 1 through 12 (of 12 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: