Forum begins after the advertisement:
Search Results for 'fader'
-
Search Results
-
Hello,
I am having issues with getting my scene transition to work. As no matter how many times I run into what should be the transition ‘doorway’ to the next scene, nothing happens at all. Any advice would be greatly appreciated!
Code Below:
Player Controller
using System.Collections; using System.Collections.Generic; using UnityEngine; public class playerController : MonoBehaviour { [SerializeField] private float walkspeed = 1; [SerializeField] private float JumpForce = 45; private int JumpBufferCounter = 0; [SerializeField] private int JumpBufferFrames; private float CoyoteTimeCounter = 0; [SerializeField] private float CoyoteTime; private int AirJumpCounter = 0; [SerializeField] private int maxAirJumps; //Ground Check Settings [SerializeField] private Transform GroundCheckPoint; [SerializeField] private float GroundCheckY = 0.2f; [SerializeField] private float GroundCheckX = 0.5f; [SerializeField] private LayerMask WhatIsGround; //Dash Settings [SerializeField] private float dashSpeed; [SerializeField] private float dashTime; [SerializeField] private float dashCooldown; //Attack Settings [SerializeField] private Transform SideAttackTransform, UpAttackTransform, DownAttackTransform; [SerializeField] private Vector2 SideAttackArea, UpAttackArea, DownAttackArea; [SerializeField] private LayerMask AttackableLayer; [SerializeField] private float timeBetweenAttack; [SerializeField] private float damage; private int stepsXRecoiled, stepsYRecoiled; // Recoil Settings [SerializeField] private int recoilXSteps = 5; [SerializeField] private int recoilYSteps = 5; [SerializeField] private float recoilXSpeed = 100; [SerializeField] private float recoilYSpeed = 100; //Health Settings public int health; public int maxHealth; [SerializeField] GameObject DamagePart; [SerializeField] float hitFlashSpeed; [HideInInspector] public PlayerStateList pState; public Rigidbody2D rb; private Animator anim; private SpriteRenderer sr; private float xAxis, yAxis; private float gravity; private bool canDash = true; private bool dashed; private bool attack = false; private float timeSinceAttack; bool restoreTime; float restoreTimeSpeed; public static playerController Instance; private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } Health = maxHealth; } // Start is called before the first frame update void Start() { pState = GetComponent<PlayerStateList>(); rb = GetComponent<Rigidbody2D>(); anim = GetComponent<Animator>(); gravity = rb.gravityScale; sr = GetComponent<SpriteRenderer>(); } 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; GetInputs(); RestoreTimeScale(); UpdateJumpVariables(); if (pState.Dashing) return; Flip(); Move(); Jump(); StartDash(); Attack(); Recoil(); FlashWhileInvincible(); } private void FixedUpdate() { if (pState.Dashing || pState.cutscene) return; Recoil(); } void GetInputs() { xAxis = Input.GetAxisRaw("Horizontal"); yAxis = Input.GetAxisRaw("Vertical"); attack = Input.GetButtonDown("attack"); } void Flip() { if (xAxis < 0) { transform.localScale = new Vector2(-Mathf.Abs(transform.localScale.x), transform.localScale.y); pState.lookingRight = false; } else if (xAxis > 0) { transform.localScale = new Vector2(Mathf.Abs(transform.localScale.x), 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 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; rb.velocity = new Vector2(transform.localScale.x * dashSpeed, 0); 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) { pState.invincible = true; //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.invincible = false; 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); } else if(yAxis > 0) { Hit(UpAttackTransform, UpAttackArea, ref pState.recoilingY, Vector2.up, recoilYSpeed); } else if (yAxis < 0 && !Grounded()) { Hit(DownAttackTransform, DownAttackArea, ref pState.recoilingY, Vector2.down, recoilYSpeed); } } } void Hit(Transform _attackTransform, Vector2 _attackArea, ref bool _recoilBool, Vector2 _recoilDir, float _recoilStrength) { Collider2D[] objectsToHit = Physics2D.OverlapBoxAll(_attackTransform.position, _attackArea, 0, AttackableLayer); List<Enemy> hitEnemies = new List<Enemy>(); if (objectsToHit.Length > 0) { _recoilBool = true; } for (int i = 0; i < objectsToHit.Length; i++) { Debug.Log("Hit"); Enemy e = objectsToHit[i].GetComponent<Enemy>(); if (objectsToHit[i].GetComponent<Enemy>() != null) { objectsToHit[i].GetComponent<Enemy>().EnemyHit(damage, _recoilDir, _recoilStrength); } } } 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) { Health -= Mathf.RoundToInt(_damage); StartCoroutine(StopTakingDamage()); } IEnumerator StopTakingDamage() { pState.invincible = true; GameObject _DamagePartParticles = Instantiate(DamagePart, transform.position, Quaternion.identity); Destroy(_DamagePartParticles, 1.5f); anim.SetTrigger("TakeDamage"); yield return new WaitForSeconds(1f); pState.invincible = false; } void FlashWhileInvincible() { if (pState.cutscene) return; sr.material.color = pState.invincible ? Color.Lerp(Color.white, Color.black, Mathf.PingPong(Time.time * hitFlashSpeed, 1.0f)) : Color.white; } void RestoreTimeScale() { if (restoreTime) { if (Time.timeScale < 1) { Time.timeScale += Time.unscaledDeltaTime * restoreTimeSpeed; } else { Time.timeScale = 1; restoreTime = false; } } } public void HitStopTime(float _newTimeScale, int _restoreSpeed, float _delay) { restoreTimeSpeed = _restoreSpeed; if (_delay > 0) { StopCoroutine(StartTimeAgain(_delay)); StartCoroutine(StartTimeAgain(_delay)); } else { restoreTime = true; } Time.timeScale = _newTimeScale; } IEnumerator StartTimeAgain(float _delay) { yield return new WaitForSecondsRealtime(_delay); restoreTime = true; } public int Health { get { return health; } set { if (health != value) { health = Mathf.Clamp(value, 0, maxHealth); } } } 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(Input.GetButtonUp("Jump") && rb.velocity.y > 0) { rb.velocity = new Vector2(rb.velocity.x, 0); pState.jumping = false; } anim.SetBool("Jumping", !Grounded()); if (!pState.jumping) { if (JumpBufferCounter >0 && CoyoteTimeCounter > 0) { rb.velocity = new Vector3(rb.velocity.x, JumpForce); pState.jumping = true; } else if(!Grounded() && AirJumpCounter < maxAirJumps && Input.GetButtonDown("Jump")) { pState.jumping = true; AirJumpCounter++; rb.velocity = new Vector3(rb.velocity.x, JumpForce); } } } void UpdateJumpVariables() { if (Grounded()) { pState.jumping = false; CoyoteTimeCounter = CoyoteTime; AirJumpCounter = 0; } else { CoyoteTimeCounter -= Time.deltaTime; } if (Input.GetButtonDown("Jump")) { JumpBufferCounter = JumpBufferFrames; } else { JumpBufferCounter--; } } }
Game Manager:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class GameManager : MonoBehaviour { public string transitionedFromScene; public Vector2 platformingRespawnPoint; public static GameManager Instance {get; private set;} private void Awake() { if(Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } DontDestroyOnLoad(gameObject); } }
Scene Fader
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; public class SceneFader : MonoBehaviour { [SerializeField] public float fadeTime; private Image fadeOutUIImage; public enum FadeDirection { In, Out } private void Awake() { fadeOutUIImage = GetComponent<Image>(); } public IEnumerator Fade(FadeDirection _fadeDirection) { float _alpha = _fadeDirection == FadeDirection.Out ? 1 : 0; float _fadeEndValue = _fadeDirection == FadeDirection.Out ? 0 : 1; if (_fadeDirection == FadeDirection.Out) { while (_alpha >= _fadeEndValue) { SetColorImage(ref _alpha, _fadeDirection); yield return null; } fadeOutUIImage.enabled = false; } else { fadeOutUIImage.enabled = true; while (_alpha <= _fadeEndValue) { SetColorImage(ref _alpha, _fadeDirection); yield return null; } } } public IEnumerator FadeAndLoadScene(FadeDirection _fadeDirection, string _sceneToLoad) { fadeOutUIImage.enabled = true; yield return Fade(_fadeDirection); SceneManager.LoadScene(_sceneToLoad); } void SetColorImage(ref float _alpha, FadeDirection _fadeDirection) { fadeOutUIImage.color = new Color(fadeOutUIImage.color.r, fadeOutUIImage.color.g, fadeOutUIImage.color.b, _alpha); _alpha += Time.deltaTime * (1 / fadeTime) * (_fadeDirection == FadeDirection.Out ? -1 : 1); } }
Scene Transition:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class SceneTransition : MonoBehaviour { [SerializeField] private string transitionTo; [SerializeField] private Transform startPoint; [SerializeField] private Vector2 exitDirection; [SerializeField] private float exitTime; private void Start() { if (GameManager.Instance.transitionedFromScene == transitionTo) { playerController.Instance.transform.position = startPoint.position; StartCoroutine(playerController.Instance.WalkIntoNewScene(exitDirection, exitTime)); } StartCoroutine(UIManager.Instance.sceneFader.Fade(SceneFader.FadeDirection.Out)); } private void OnTriggerEnter2D(Collider2D _other) { if (_other.CompareTag("Player")) { GameManager.Instance.transitionedFromScene = SceneManager.GetActiveScene().name; playerController.Instance.pState.cutscene = true; playerController.Instance.pState.invincible = true; StartCoroutine(UIManager.Instance.sceneFader.FadeAndLoadScene(SceneFader.FadeDirection.In, transitionTo)); } } }
UI Manager
using System.Collections; using System.Collections.Generic; using UnityEngine; public class UIManager : MonoBehaviour { public SceneFader sceneFader; public static UIManager Instance; private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } DontDestroyOnLoad(gameObject); sceneFader = GetComponentInChildren<SceneFader>(); } }
Hi everyone, I’m on the way to make the scene fading but got some trouble with it now.
Firstly when I start the game, the image not was render under the game build like the video. Don’t know that does I miss anything in the video. Here is the scene fader of my
and here is the Inspector of it
If i turn off the image and start the game, there is some error happend in the console
the first two error happand with start of the game. The third error happend when I get to the scene transition point. My character keep moving and the error happend.
Here is the scene transition codeusing System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class SceneTransition : MonoBehaviour { // Start is called before the first frame update [SerializeField] private string transitionTo; [SerializeField] private Transform startPoint; [SerializeField] private Vector2 directionExit; [SerializeField] private float exitTime; private void Start() { if (transitionTo == GameManager.Instance.transitionFromScene) { Move.Instance.transform.position = startPoint.position; StartCoroutine(Move.Instance.WalktonewScene(directionExit,exitTime)); } StartCoroutine(UIManager.Instance.sceneFading.Fade(SceneFading.fadeDirection.Out)); } private void OnTriggerEnter2D(Collider2D _other) { if (_other.CompareTag("Player")) { GameManager.Instance.transitionFromScene = SceneManager.GetActiveScene().name; Move.Instance.playerStateList.incutscene = true; StartCoroutine(UIManager.Instance.sceneFading.FadeAndLoadScene(SceneFading.fadeDirection.In,transitionTo)); } } }
the scenefading script
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; public class SceneFading : MonoBehaviour { [SerializeField] private float fadeTime; private Image fadeoutUIImage; public enum fadeDirection { In, Out } // Start is called before the first frame update void Awake() { fadeoutUIImage = GetComponent<Image>(); } // Update is called once per frame void Update() { } public IEnumerator Fade(fadeDirection _fadeDirection) { float _alpha = _fadeDirection == fadeDirection.Out ? 1 : 0; float _fadeEndValue = _fadeDirection == fadeDirection.Out ? 0 : 1; if (_fadeDirection == fadeDirection.Out) { while (_alpha >= _fadeEndValue) { setColorImage(ref _alpha,_fadeDirection); yield return null; } fadeoutUIImage.enabled = false; } else { fadeoutUIImage.enabled = true; while(_alpha <= _fadeEndValue) { setColorImage(ref _alpha,_fadeDirection); yield return null; } } } public IEnumerator FadeAndLoadScene(fadeDirection _fadeDirection, string _sceneToLoad) { fadeoutUIImage.enabled = true ; yield return Fade(_fadeDirection); SceneManager.LoadScene(_sceneToLoad); } void setColorImage(ref float _alpha, fadeDirection _fadeDirection) { fadeoutUIImage.color = new Color(fadeoutUIImage.color.r, fadeoutUIImage.color.g, fadeoutUIImage.color.b, _alpha); _alpha += Time.deltaTime * (1/fadeTime) * (_fadeDirection == fadeDirection.Out ? -1 : 1); } }
I already change the start from scene fading to the Awake but still cannot fix the null refference.
Can you guys help me to make the black image render behind the game and fix this bug?Hello everyone! I have a problem again, but it’s not so significant anymore, in short, the first is that my enemy doesn’t take damage from spells at all, and the second is that when I press the button to heal, my character freezes with the healing animation and does nothing else. I also want to note that there are no errors either in Unit or in the console with the code itself. Sorry to bother you again, I hope you can help me with something. Thank you in advance.
Video: https://i.imgur.com/jHXB0rM.mp4
Code of my PlayerController:
using System.Collections; using System.Collections.Generic; using System.Net.Sockets; using UnityEngine; using UnityEngine.UIElements; using UnityEngine.UI; public class PlayerController : MonoBehaviour { [Header("Horizontal Movement Settings:")] [SerializeField] private float walkSpeed = 1; //sets the players movement speed on the ground [Space(5)] [Header("Vertical Movement Settings")] [SerializeField] private float jumpForce = 45f; //sets how hight the player can jump private int jumpBufferCounter = 0; //stores the jump button input [SerializeField] private int jumpBufferFrames; //sets the max amount of frames the jump buffer input is stored private float coyoteTimeCounter = 0; //stores the Grounded() bool [SerializeField] private float coyoteTime; ////sets the max amount of frames the Grounded() bool is stored private int airJumpCounter = 0; //keeps track of how many times the player has jumped in the air [SerializeField] private int maxAirJumps; //the max no. of air jumps private float gravity; //stores the gravity scale at start [Space(5)] [Header("Ground Check Settings:")] [SerializeField] private Transform groundCheckPoint; //point at which ground check happens [SerializeField] private float groundCheckY = 0.2f; //how far down from ground chekc point is Grounded() checked [SerializeField] private float groundCheckX = 0.5f; //how far horizontally from ground chekc point to the edge of the player is [SerializeField] private LayerMask whatIsGround; //sets the ground layer [Space(5)] [Header("Dash Settings")] [SerializeField] private float dashSpeed; //speed of the dash [SerializeField] private float dashTime; //amount of time spent dashing [SerializeField] private float dashCooldown; //amount of time between dashes [SerializeField] GameObject dashEffect; private bool canDash = true, dashed; [Space(5)] [Header("Attack Settings:")] [SerializeField] private Transform SideAttackTransform; //the middle of the side attack area [SerializeField] private Vector2 SideAttackArea; //how large the area of side attack is [SerializeField] private Transform UpAttackTransform; //the middle of the up attack area [SerializeField] private Vector2 UpAttackArea; //how large the area of side attack is [SerializeField] private Transform DownAttackTransform; //the middle of the down attack area [SerializeField] private Vector2 DownAttackArea; //how large the area of down attack is [SerializeField] private LayerMask attackableLayer; //the layer the player can attack and recoil off of private float timeBetweenAttack, timeSinceAttck; [SerializeField] private float damage; //the damage the player does to an enemy [SerializeField] private GameObject slashEffect; //the effect of the slashs bool restoreTime; float restoreTimeSpeed; [Space(5)] [Header("Recoil Settings:")] [SerializeField] private int recoilXSteps = 5; //how many FixedUpdates() the player recoils horizontally for [SerializeField] private int recoilYSteps = 5; //how many FixedUpdates() the player recoils vertically for [SerializeField] private float recoilXSpeed = 100; //the speed of horizontal recoil [SerializeField] private float recoilYSpeed = 100; //the speed of vertical recoil private int stepsXRecoiled, stepsYRecoiled; //the no. of steps recoiled horizontally and verticall [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; [Space(5)] [Header("Spell Settings")] //spell stats [SerializeField] float manaSpellCost = 0.3f; [SerializeField] float timeBetweenCast = 0.5f; float timeSinceCast; [SerializeField] float spellDamage; //upspellexplosion and downspellfireball [SerializeField] float downSpellForce; // desolate dive only //spell cast objects [SerializeField] GameObject sideSpellFireball; [SerializeField] GameObject upSpellExplosion; [SerializeField] GameObject downSpellFireball; [Space(5)] [HideInInspector] public PlayerStateList pState; private Animator anim; private Rigidbody2D rb; private SpriteRenderer sr; //Input Variables private float xAxis, yAxis; private bool attack = false; 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; } 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; GetInputs(); UpdateJumpVariables(); if (pState.dashing || pState.healing) return; Flip(); Move(); Jump(); StartDash(); Attack(); RestoreTimeScale(); FlashWhileInvincible(); Heal(); CastSpell(); } private void OnTriggerEnter2D(Collider2D _other) //for up and down cast spell { 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) return; Recoil(); } void GetInputs() { xAxis = Input.GetAxisRaw("Horizontal"); yAxis = Input.GetAxisRaw("Vertical"); attack = Input.GetButtonDown("Attack"); } void Flip() { if (xAxis < 0) { transform.localScale = new Vector2(-3, transform.localScale.y); pState.lookingRight = false; } else if (xAxis > 0) { transform.localScale = new Vector2(3, transform.localScale.y); pState.lookingRight = true; } } private void Move() { if (pState.healing) rb.velocity = new Vector2(0, 0); rb.velocity = new Vector2(walkSpeed * xAxis, rb.velocity.y); anim.SetBool("Walking", rb.velocity.x != 0 && Grounded()); } 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); if (!Grounded()) Instantiate(dashEffect, transform); yield return new WaitForSecondsRealtime(dashTime); rb.gravityScale = gravity; pState.dashing = false; yield return new WaitForSecondsRealtime(dashCooldown); canDash = true; } public IEnumerator WalkIntoNewScene(Vector2 _exitDir, float _delay) { if(_exitDir.y > 0) { rb.velocity = jumpForce * _exitDir; } if (_exitDir.x != 0) { xAxis = _exitDir.x > 0 ? 1: -1; Move(); } Flip(); yield return new WaitForSecondsRealtime(_delay); pState.cutscene = false; } void Attack() { timeSinceAttck += Time.deltaTime; if (attack && timeSinceAttck >= timeBetweenAttack) { timeSinceAttck = 0; anim.SetTrigger("Attacking"); if (yAxis == 0 || yAxis < 0 && Grounded()) { Hit(SideAttackTransform, SideAttackArea, ref pState.recoilingX, recoilXSpeed); Instantiate(slashEffect, SideAttackTransform); } else if (yAxis > 0) { Hit(UpAttackTransform, UpAttackArea, ref pState.recoilingY, recoilYSpeed); SlashEffectAtAngle(slashEffect, 80, UpAttackTransform); } else if (yAxis < 0 && !Grounded()) { Hit(DownAttackTransform, DownAttackArea, ref pState.recoilingY, recoilYSpeed); SlashEffectAtAngle(slashEffect, -90, DownAttackTransform); } } } void Hit(Transform _attackTransform, Vector2 _attackArea, ref bool _recoilDir, float _recoilStrength) { Collider2D[] objectsToHit = Physics2D.OverlapBoxAll(_attackTransform.position, _attackArea, 0, attackableLayer); if (objectsToHit.Length > 0) { _recoilDir = true; } for (int i = 0; i < objectsToHit.Length; i++) { if (objectsToHit[i].GetComponent<Enemy>() != null) { objectsToHit[i].GetComponent<Enemy>().EnemyHit (damage, (transform.position - objectsToHit[i].transform.position).normalized, _recoilStrength); 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 / 3, transform.localScale.y / 3); } 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) { Health -= Mathf.RoundToInt(_damage); 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 WaitForSecondsRealtime(1f); pState.invincible = false; } void FlashWhileInvincible() { sr.material.color = pState.invincible ? Color.Lerp(Color.white, Color.black, Mathf.PingPong(Time.time * hitFlashSpeed, 1.0f)) : Color.white; } void RestoreTimeScale() { if (restoreTime) { if (Time.timeScale < 1) { Time.timeScale += Time.unscaledDeltaTime * restoreTimeSpeed; } else { Time.timeScale = 1; restoreTime = false; } } } public void HitStopTime(float _newTimeScale, int _restoreSpeed, float _delay) { restoreTimeSpeed = _restoreSpeed; if (_delay > 0) { StopCoroutine(StartTimeAgain(_delay)); StartCoroutine(StartTimeAgain(_delay)); } else { restoreTime = true; } Time.timeScale = _newTimeScale; } IEnumerator StartTimeAgain(float _delay) { yield return new WaitForSecondsRealtime(_delay); restoreTime = true; } 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("Healing") && Health < maxHealth && Mana > 0 && Grounded() && !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) { mana = Mathf.Clamp(value, 0, 1); manaStorage.fillAmount = Mana; } } } void CastSpell() { if (Input.GetButtonDown("CastSpell") && timeSinceCast >= timeBetweenCast && Mana >= manaSpellCost) { pState.casting = true; timeSinceCast = 0; StartCoroutine(CastCoroutine()); } else { timeSinceCast += Time.deltaTime; } 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 WaitForSecondsRealtime(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 WaitForSecondsRealtime(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) { pState.jumping = false; rb.velocity = new Vector2(rb.velocity.x, 0); } 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--; } } }
Code of PlayerStateList:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerStateList : MonoBehaviour { public bool jumping = false; public bool dashing = false; public bool recoilingX, recoilingY; public bool lookingRight; public bool invincible; public bool healing; public bool casting; public bool cutscene = false; }
UIManager:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class UIManager : MonoBehaviour { public SceneFader sceneFader; public static UIManager Instance; private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } DontDestroyOnLoad(gameObject); sceneFader = GetComponentInChildren<SceneFader>(); } }
HeartController:
using UnityEngine; using UnityEngine.UI; public class HeartController : MonoBehaviour { private GameObject[] heartContainers; private Image[] heartFills; public Transform heartsParent; public GameObject heartContainerPrefab; // Start is called before the first frame update void Start() { heartContainers = new GameObject[PlayerController.Instance.maxHealth]; heartFills = new Image[PlayerController.Instance.maxHealth]; PlayerController.Instance.onHealthChangedCallback += UpdateHeartsHUD; InstantiateHeartContainers(); UpdateHeartsHUD(); } // Update is called once per frame void Update() { } void SetHeartContainers() { for (int i = 0; i < heartContainers.Length; i++) { if (i < PlayerController.Instance.maxHealth) { heartContainers[i].SetActive(true); } else { heartContainers[i].SetActive(false); } } } void SetFilledHearts() { for (int i = 0; i < heartFills.Length; i++) { if (i < PlayerController.Instance.health) { heartFills[i].fillAmount = 1; } else { heartFills[i].fillAmount = 0; } } } void InstantiateHeartContainers() { for (int i = 0; i < PlayerController.Instance.maxHealth; i++) { GameObject temp = Instantiate(heartContainerPrefab); temp.transform.SetParent(heartsParent, false); heartContainers[i] = temp; heartFills[i] = temp.transform.Find("HeartFill").GetComponent<Image>(); } } void UpdateHeartsHUD() { SetHeartContainers(); SetFilledHearts(); } }
FireBall:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class FireBall : MonoBehaviour { [SerializeField] float damage; [SerializeField] float hitForce; [SerializeField] int speed; [SerializeField] float lifetime = 1; // Start is called before the first frame update void Start() { Destroy(gameObject, lifetime); } private void FixedUpdate() { transform.position += speed * transform.right; } //detect hit private void OnTriggerEnter2D(Collider2D _other) { if (_other.tag == "Enemy") { _other.GetComponent<Enemy>().EnemyHit(damage, (_other.transform.position - transform.position).normalized, -hitForce); } } }
Enemy:
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; protected float recoilTimer; protected Rigidbody2D rb; // Start is called before the first frame update protected virtual void Start() { rb = GetComponent<Rigidbody2D>(); } // Update is called once per frame protected virtual void Update() { if (health <= 0) { Destroy(gameObject); } if (isRecoiling) { if (recoilTimer < recoilLength) { recoilTimer += Time.deltaTime; } else { isRecoiling = false; recoilTimer = 0; } } } public virtual void EnemyHit(float _damageDone, Vector2 _hitDirection, float _hitForce) { health -= _damageDone; if (!isRecoiling) { rb.AddForce(-_hitForce * recoilFactor * _hitDirection); } } protected void OnCollisionStay2D(Collision2D _other) { if (_other.gameObject.CompareTag("Player") && !PlayerController.Instance.pState.invincible) { Attack(); PlayerController.Instance.HitStopTime(0, 5, 0.5f); } } protected virtual void Attack() { PlayerController.Instance.TakeDamage(damage); } }
Skeleton_Warrior:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Skeleton_Warrior : Enemy { // Start is called before the first frame update protected override void Start() { base.Start(); rb.gravityScale = 12f; } // Update is called once per frame protected override void Update() { base.Update(); if (!isRecoiling) { transform.position = Vector2.MoveTowards (transform.position, new Vector2(PlayerController.Instance.transform.position.x, transform.position.y), speed * Time.deltaTime); } } public override void EnemyHit(float _damageDone, Vector2 _hitDirection, float _hitForce) { base.EnemyHit(_damageDone, _hitDirection, _hitForce); } }
Hi! I’m facing a NullReferenceException error in my Unity project, and I’m not sure how to resolve it. The error message is:
NullReferenceException: Object reference not set to an instance of an object SceneTransition.Awake() (at Assets/code/SceneTransition.cs:27)
in short, I wrote code for sceneFader and everything worked perfectly, but after I added the lighting to the scene, everything stopped working and started giving this error.
Here is video :
https://i.imgur.com/Ow2POcI.mp4
Here is my code from SceneTransition:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class SceneTransition : MonoBehaviour { // Start is called before the first frame update [SerializeField] private string transitionTo; [SerializeField] private Transform startPoint; [SerializeField] private Vector2 exitDirection; [SerializeField] private float exitTime; private void Awake() { if (GameManager.Instance.transitionedFromScene == transitionTo) { PlayerController.Instance.transform.position = startPoint.position; StartCoroutine(PlayerController.Instance.WalkIntoNewScene(exitDirection, exitTime)); } StartCoroutine(UIManager.Instance.sceneFader.Fade(SceneFader.FadeDirection.Out)); } private void OnTriggerEnter2D(Collider2D _other) { if (_other.CompareTag("Player")) { GameManager.Instance.transitionedFromScene = SceneManager.GetActiveScene().name; PlayerController.Instance.pState.cutscene = true; StartCoroutine(UIManager.Instance.sceneFader.FadeAndLoadScene(SceneFader.FadeDirection.In, transitionTo)); } } }
Here is code of UIManager:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class UIManager : MonoBehaviour { public SceneFader sceneFader; public static UIManager Instance; private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } DontDestroyOnLoad(gameObject); sceneFader = GetComponentInChildren<SceneFader>(); } }
Here is code of GameManager:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class GameManager : MonoBehaviour { public string transitionedFromScene; public static GameManager Instance { get; private set; } private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } DontDestroyOnLoad(gameObject); } }
Here is code of SceneFader:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; public class SceneFader : MonoBehaviour { [SerializeField] private float fadeTime; private Image fadeOutUIImage; public enum FadeDirection { In, Out } // Start is called before the first frame update void Start() { fadeOutUIImage = GetComponent<Image>(); } // Update is called once per frame void Update() { } public IEnumerator Fade(FadeDirection _fadeDirection) { float _alpha = _fadeDirection == FadeDirection.Out ? 1 : 0; float _fadeEndValue = _fadeDirection == FadeDirection.Out ? 0 : 1; if (_fadeDirection == FadeDirection.Out) { while (_alpha >= _fadeEndValue) { SetColorImage(ref _alpha, _fadeDirection); yield return null; } fadeOutUIImage.enabled = false; } else { fadeOutUIImage.enabled = true; while (_alpha <= _fadeEndValue) { SetColorImage(ref _alpha, _fadeDirection); yield return null; } } } public IEnumerator FadeAndLoadScene(FadeDirection _fadeDirection, string _sceneToLoad) { fadeOutUIImage.enabled = true; yield return Fade(_fadeDirection); SceneManager.LoadScene(_sceneToLoad); } void SetColorImage(ref float _alpha, FadeDirection _fadeDirection) { fadeOutUIImage.color = new Color(fadeOutUIImage.color.r, fadeOutUIImage.color.g, fadeOutUIImage.color.b, _alpha); _alpha += Time.deltaTime * (1 / fadeTime) * (_fadeDirection == FadeDirection.Out ? -1 : 1); } }
Here is code of PlayerStateList:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerStateList : MonoBehaviour { public bool jumping = false; public bool dashing = false; public bool recoilingX, recoilingY; public bool lookingRight; public bool invincible; public bool healing; public bool casting; public bool cutscene = false; }
And Here is code of PlayerController:
using System.Collections; using System.Collections.Generic; using System.Net.Sockets; using UnityEngine; using UnityEngine.UIElements; using UnityEngine.UI; public class PlayerController : MonoBehaviour { [Header("Horizontal Movement Settings:")] [SerializeField] private float walkSpeed = 1; //sets the players movement speed on the ground [Space(5)] [Header("Vertical Movement Settings")] [SerializeField] private float jumpForce = 45f; //sets how hight the player can jump private int jumpBufferCounter = 0; //stores the jump button input [SerializeField] private int jumpBufferFrames; //sets the max amount of frames the jump buffer input is stored private float coyoteTimeCounter = 0; //stores the Grounded() bool [SerializeField] private float coyoteTime; ////sets the max amount of frames the Grounded() bool is stored private int airJumpCounter = 0; //keeps track of how many times the player has jumped in the air [SerializeField] private int maxAirJumps; //the max no. of air jumps private float gravity; //stores the gravity scale at start [Space(5)] [Header("Ground Check Settings:")] [SerializeField] private Transform groundCheckPoint; //point at which ground check happens [SerializeField] private float groundCheckY = 0.2f; //how far down from ground chekc point is Grounded() checked [SerializeField] private float groundCheckX = 0.5f; //how far horizontally from ground chekc point to the edge of the player is [SerializeField] private LayerMask whatIsGround; //sets the ground layer [Space(5)] [Header("Dash Settings")] [SerializeField] private float dashSpeed; //speed of the dash [SerializeField] private float dashTime; //amount of time spent dashing [SerializeField] private float dashCooldown; //amount of time between dashes [SerializeField] GameObject dashEffect; private bool canDash = true, dashed; [Space(5)] [Header("Attack Settings:")] [SerializeField] private Transform SideAttackTransform; //the middle of the side attack area [SerializeField] private Vector2 SideAttackArea; //how large the area of side attack is [SerializeField] private Transform UpAttackTransform; //the middle of the up attack area [SerializeField] private Vector2 UpAttackArea; //how large the area of side attack is [SerializeField] private Transform DownAttackTransform; //the middle of the down attack area [SerializeField] private Vector2 DownAttackArea; //how large the area of down attack is [SerializeField] private LayerMask attackableLayer; //the layer the player can attack and recoil off of private float timeBetweenAttack, timeSinceAttck; [SerializeField] private float damage; //the damage the player does to an enemy [SerializeField] private GameObject slashEffect; //the effect of the slashs bool restoreTime; float restoreTimeSpeed; [Space(5)] [Header("Recoil Settings:")] [SerializeField] private int recoilXSteps = 5; //how many FixedUpdates() the player recoils horizontally for [SerializeField] private int recoilYSteps = 5; //how many FixedUpdates() the player recoils vertically for [SerializeField] private float recoilXSpeed = 100; //the speed of horizontal recoil [SerializeField] private float recoilYSpeed = 100; //the speed of vertical recoil private int stepsXRecoiled, stepsYRecoiled; //the no. of steps recoiled horizontally and verticall [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; [Space(5)] [Header("Spell Settings")] //spell stats [SerializeField] float manaSpellCost = 0.3f; [SerializeField] float timeBetweenCast = 0.5f; float timeSinceCast; [SerializeField] float spellDamage; //upspellexplosion and downspellfireball [SerializeField] float downSpellForce; // desolate dive only //spell cast objects [SerializeField] GameObject sideSpellFireball; [SerializeField] GameObject upSpellExplosion; [SerializeField] GameObject downSpellFireball; [Space(5)] [HideInInspector] public PlayerStateList pState; private Animator anim; private Rigidbody2D rb; private SpriteRenderer sr; //Input Variables private float xAxis, yAxis; private bool attack = false; 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; } 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; GetInputs(); UpdateJumpVariables(); if (pState.dashing || pState.healing) return; Flip(); Move(); Jump(); StartDash(); Attack(); RestoreTimeScale(); FlashWhileInvincible(); Heal(); CastSpell(); } private void OnTriggerEnter2D(Collider2D _other) //for up and down cast spell { 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) return; Recoil(); } void GetInputs() { xAxis = Input.GetAxisRaw("Horizontal"); yAxis = Input.GetAxisRaw("Vertical"); attack = Input.GetButtonDown("Attack"); } void Flip() { if (xAxis < 0) { transform.localScale = new Vector2(-3, transform.localScale.y); pState.lookingRight = false; } else if (xAxis > 0) { transform.localScale = new Vector2(3, 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 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); 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(_exitDir.y > 0) { rb.velocity = jumpForce * _exitDir; } if (_exitDir.x != 0) { xAxis = _exitDir.x > 0 ? 1: -1; Move(); } Flip(); yield return new WaitForSeconds(_delay); pState.cutscene = false; } void Attack() { timeSinceAttck += Time.deltaTime; if (attack && timeSinceAttck >= timeBetweenAttack) { timeSinceAttck = 0; anim.SetTrigger("Attacking"); if (yAxis == 0 || yAxis < 0 && Grounded()) { Hit(SideAttackTransform, SideAttackArea, ref pState.recoilingX, recoilXSpeed); Instantiate(slashEffect, SideAttackTransform); } else if (yAxis > 0) { Hit(UpAttackTransform, UpAttackArea, ref pState.recoilingY, recoilYSpeed); SlashEffectAtAngle(slashEffect, 80, UpAttackTransform); } else if (yAxis < 0 && !Grounded()) { Hit(DownAttackTransform, DownAttackArea, ref pState.recoilingY, recoilYSpeed); SlashEffectAtAngle(slashEffect, -90, DownAttackTransform); } } } void Hit(Transform _attackTransform, Vector2 _attackArea, ref bool _recoilDir, float _recoilStrength) { Collider2D[] objectsToHit = Physics2D.OverlapBoxAll(_attackTransform.position, _attackArea, 0, attackableLayer); if (objectsToHit.Length > 0) { _recoilDir = true; } for (int i = 0; i < objectsToHit.Length; i++) { if (objectsToHit[i].GetComponent<Enemy>() != null) { objectsToHit[i].GetComponent<Enemy>().EnemyHit (damage, (transform.position - objectsToHit[i].transform.position).normalized, _recoilStrength); 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 / 3, transform.localScale.y / 3); } 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) { Health -= Mathf.RoundToInt(_damage); 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; } void FlashWhileInvincible() { sr.material.color = pState.invincible ? Color.Lerp(Color.white, Color.black, Mathf.PingPong(Time.time * hitFlashSpeed, 1.0f)) : Color.white; } 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; if (_delay > 0) { StopCoroutine(StartTimeAgain(_delay)); StartCoroutine(StartTimeAgain(_delay)); } else { restoreTime = true; } Time.timeScale = _newTimeScale; } IEnumerator StartTimeAgain(float _delay) { restoreTime = true; yield return new WaitForSeconds(_delay); } 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("Healing") && 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) { mana = Mathf.Clamp(value, 0, 1); manaStorage.fillAmount = Mana; } } } void CastSpell() { if (Input.GetButtonDown("CastSpell") && timeSinceCast >= timeBetweenCast && Mana >= manaSpellCost) { pState.casting = true; timeSinceCast = 0; StartCoroutine(CastCoroutine()); } else { timeSinceCast += Time.deltaTime; } 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; 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--; } } }
Advertisement below: