Forum begins after the advertisement:

 


Search Results for 'fader'

Home Forums Search Search Results for 'fader'

Viewing 15 results - 1 through 15 (of 94 total)
  • Author
    Search Results
  • #17838
    Terence
    Keymaster

    @nabilgaming did you make any changes to the SceneFader script as shared on the article / video?

    #17826
    Ser Apustaja
    AI Assistant
    (BETA)

    If you prefer not to use either of the previous solutions (disabling the fader or using a Canvas Group), another approach would be to adjust the fader’s visibility directly through its rendering properties or by controlling its behavior with a script. Here are a couple of alternative ideas:

    1. Adjusting the Alpha Directly

    Instead of using a Canvas Group, you can manipulate the alpha of the fader’s material or color directly. This can be done without disabling the GameObject:

    public Image faderImage; // Assuming you're using a UI Image for the fader
    
    public void SetFaderVisibility(float alpha)
    {
        Color color = faderImage.color;
        color.a = alpha; // Set the alpha value
        faderImage.color = color;
    }

    You can call this method with 0 to make it fully transparent or 1 to make it fully opaque.

    2. Moving the Fader Off-Screen

    If you want the fader to be completely out of view instead of disabling it or changing its alpha, you can move it off-screen. This way, it won’t cover the main content while still being part of the scene:

    public RectTransform faderTransform; // Assuming this is a RectTransform
    
    public void MoveFaderOffScreen()
    {
        faderTransform.anchoredPosition = new Vector2(-Screen.width, 0); // Move it to the left off-screen
    }
    
    public void MoveFaderOnScreen()
    {
        faderTransform.anchoredPosition = Vector2.zero; // Reset to center
    }

    3. Using a Coroutine for Smooth Transition

    If you want the fader to smoothly transition in and out, you can use a coroutine to gradually adjust its position or alpha:

    private IEnumerator MoveFader(float targetPositionX, float duration)
    {
        Vector2 startPos = faderTransform.anchoredPosition;
        Vector2 targetPos = new Vector2(targetPositionX, startPos.y);
        float elapsed = 0f;
    
        while (elapsed < duration)
        {
            elapsed += Time.deltaTime;
            faderTransform.anchoredPosition = Vector2.Lerp(startPos, targetPos, elapsed / duration);
            yield return null;
        }
    
        faderTransform.anchoredPosition = targetPos; // Ensure it reaches the target position
    }
    
    // Call this method to move it off-screen
    public void HideFader(float duration)
    {
        StartCoroutine(MoveFader(-Screen.width, duration));
    }
    
    // Call this method to move it back on-screen
    public void ShowFader(float duration)
    {
        StartCoroutine(MoveFader(0, duration));
    }

    Conclusion

    These alternative solutions allow you to manage the visibility of your scene fader without disabling it or using a Canvas Group. Choose the one that best fits your project's needs! If you have more specific requirements or constraints, feel free to share them for tailored advice!

    #17824
    Ser Apustaja
    AI Assistant
    (BETA)

    It sounds like you are considering two options for managing your scene fader: disabling it when you don’t want it to cover the screen or using a Canvas Group to control its visibility. Here are some tips for both approaches:

    Disabling the Scene Fader

    If you choose to disable the fader, you can do this programmatically when you want to prevent it from covering the screen. For example, in Unity, you might do something like this:

    // Assuming your fader is a GameObject
    public GameObject sceneFader;
    
    // Call this method to disable the fader
    public void DisableFader()
    {
        sceneFader.SetActive(false);
    }
    
    // Call this method to enable the fader
    public void EnableFader()
    {
        sceneFader.SetActive(true);
    }

    Using Canvas Group

    If you want to keep the fader in the scene but control its visibility, using a CanvasGroup is a great way to do this. You can adjust the alpha value to make it transparent or opaque without disabling the GameObject. Here’s how you can do it:

    1. Add a CanvasGroup component to your fader GameObject.
    2. Use the following code to control its visibility:
    // Assuming your fader has a CanvasGroup component
    public CanvasGroup canvasGroup;
    
    // Call this method to fade out the fader
    public void FadeOutFader(float duration)
    {
        StartCoroutine(FadeCanvasGroup(canvasGroup, canvasGroup.alpha, 0, duration));
    }
    
    // Call this method to fade in the fader
    public void FadeInFader(float duration)
    {
        StartCoroutine(FadeCanvasGroup(canvasGroup, canvasGroup.alpha, 1, duration));
    }
    
    private IEnumerator FadeCanvasGroup(CanvasGroup cg, float start, float end, float duration)
    {
        float elapsed = 0f;
    
        while (elapsed < duration)
        {
            elapsed += Time.deltaTime;
            cg.alpha = Mathf.Lerp(start, end, elapsed / duration);
            yield return null;
        }
    
        cg.alpha = end; // Ensure it ends on the target value
    }

    Conclusion

    Choose the approach that best fits your needs. If you want to completely remove the fader from the scene, disabling it is the way to go. If you want to keep it active but control its visibility, using a CanvasGroup will work well. If you have any specific questions about your implementation, feel free to ask!

    #17823
    Pool ForReal
    Participant

    i must disable my scene fader if don’t want the fader cover the screen or add canvas group. @Terence

    View post on imgur.com
    #17822
    Ser Apustaja
    AI Assistant
    (BETA)

    It sounds like you’re having an issue with your scene fader being too close to the edges, causing it to not display anything properly. Here are a few suggestions to troubleshoot and potentially fix the issue:

    1. Adjust the Size of the Fader: Make sure that the size of your scene fader is set correctly. If it’s too small, it might not cover the entire screen. Check the width and height properties of your scene fader.

    2. Positioning: Ensure that the position of the fader is set to the correct coordinates. It should typically be centered or positioned to cover the entire view area.

    3. Z-Index: If you’re using a layering system, ensure that the scene fader has a higher z-index than other UI elements. This will ensure that it appears on top of everything else.

    4. Opacity Settings: If your fader has an opacity setting, make sure it is not set to 0. You should set it to a value that allows it to be visible (e.g., 1 for fully opaque).

    5. Testing with Different Colors: Temporarily change the color of the fader to something that stands out (like red or green) to see if it is appearing at all.

    6. Debugging: If you’re using a game engine like Unity or Unreal Engine, use debugging tools to check if the fader is being rendered and if there are any warnings or errors related to it.

    If you could provide more details about the platform or framework you are using, I could give more specific advice or code snippets to help you resolve this issue!

    #17821
    Pool ForReal
    Participant

    if i enable scene fader my scene fader too close until not show anything

    View post on imgur.com
    Bachok
    Participant

    Problem Description:

    1. Respawn Button Stops Working After Scene Transition: On the current scene, the respawn button correctly calls the OnRespawnButtonClicked() method, which finds the Bonfire object and calls its RespawnPlayer() method.

    After transitioning to another scene, the button stops responding to clicks. Clicking the button does not trigger any actions, and no messages about the method being called appear in the console. What Doesn’t Work:

    1. Respawn Button: After transitioning to another scene, the button does not respond to clicks.

    Possible reasons:

    The reference to the OnRespawnButtonClicked() method is lost after loading a new scene.

    The Bonfire object is not found on the new scene, so FindObjectOfType<Bonfire>() returns null. Here is my code:

    SceneTransiotion:

    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 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;
    
                StartCoroutine(UIManager.Instance.sceneFader.FadeAndLoadScene(SceneFader.FadeDirection.In, transitionTo));
            }
        }
    }
    

    PlayerController:

    using System.Collections;
    using System.Collections.Generic;
    using System.Net.Sockets;
    using UnityEngine;
    using UnityEngine.UIElements;
    using UnityEngine.UI;
    using Unity.VisualScripting;
    
    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;
    
        public 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")]
        //spell stats
        [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)]
    
    
        [HideInInspector] public PlayerStateList pState;
        private Animator anim;
        public Rigidbody2D rb;
        private SpriteRenderer sr;
    
        [Header("Camera Settings")]
        public float playerFallSpeedThreshold = -10;
    
        //Input Variables
        private float xAxis, yAxis;
        private bool attack = false;
        bool openMap;
    
        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.alive) return;
    
            if (pState.cutscene) return;
    
            GetInputs();
    
            ToggleMap();
    
            UpdateJumpVariables();
            UpdateCameraYDampForPlayerFall();
            if (pState.dashing) return;
            RestoreTimeScale();
            FlashWhileInvincible();
            Move();
            Heal();
            CastSpell();
    
            if (pState.healing) return;
            Flip();
            Jump();
            StartDash();
            Attack();
            Recoil();
            if (Input.GetKeyDown(KeyCode.L))
            {
                StartCoroutine(Death());
            }
        }
        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 || pState.healing) return;
            Recoil();
        }
    
        void GetInputs()
        {
            xAxis = Input.GetAxisRaw("Horizontal");
            yAxis = Input.GetAxisRaw("Vertical");
            attack = Input.GetButtonDown("Attack");
            openMap = Input.GetButton("Map");
    
    
        }
        void ToggleMap()
        {
            if (openMap)
            {
                UIManager.Instance.mapHandler.SetActive(true);
            }
            else
            {
                UIManager.Instance.mapHandler.SetActive(false);
            }
        }
        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 UpdateCameraYDampForPlayerFall()
        {
            if(rb.velocity.y < playerFallSpeedThreshold && !CameraManager.Instance.isLerpingYDamping && !CameraManager.Instance.hasLerpingYDamping)
            {
                StartCoroutine(CameraManager.Instance.LerpYDamping(true));
            }
            if(rb.velocity.y >= 0 && !CameraManager.Instance.isLerpingYDamping && CameraManager.Instance.hasLerpingYDamping)
            {
                CameraManager.Instance.hasLerpingYDamping = 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);
            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 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 WaitForSecondsRealtime(_delay);
            print("cutscene played");
            pState.cutscene = false;
        }
    
        void Attack()
        {
            timeSinceAttck += Time.deltaTime;
            if (attack && timeSinceAttck >= timeBetweenAttack)
            {
                timeSinceAttck = 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 / 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)
        {
            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 WaitForSecondsRealtime(1f);
            pState.invincible = false;
        }
    
        IEnumerator Flash()
        {
            sr.enabled = !sr.enabled;
            canFlash = false;
            yield return new WaitForSecondsRealtime(0.1f);
            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;
            if (_delay > 0)
            {
                StopCoroutine(StartTimeAgain(_delay));
                StartCoroutine(StartTimeAgain(_delay));
            }
            else
            {
                restoreTime = true;
            }
            Time.timeScale = _newTimeScale;
        }
        IEnumerator StartTimeAgain(float _delay)
        {
            restoreTime = true;
            yield return new WaitForSecondsRealtime(_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("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("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)
                {
                    if (!halfMana)
                    {
                        mana = Mathf.Clamp(value, 0, 1);
                    }
                    else
                    {
                        mana = Mathf.Clamp(value, 0, 0.5f);
                    }
                    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
            // down cast
    else if (yAxis < 0 && !Grounded())
    {
        downSpellFireball.SetActive(true);
    
        // Додаємо віддачу вгору після заклинання
        rb.velocity = new Vector2(rb.velocity.x, recoilYSpeed); 
        pState.recoilingY = 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--;
            }
        }
    }
    

    UIManager:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class UIManager : MonoBehaviour
    {
        public SceneFader sceneFader;
    
        public static UIManager Instance;
    
        [SerializeField] GameObject deathScreen;
    
        public GameObject mapHandler;
    
        [SerializeField] GameObject halfMana, fullMana;
    
        public enum ManaState
        {
            FullMana,
            HalfMana
        }
        public ManaState manaState;
        private void Awake()
        {
            if (Instance != null && Instance != this)
            {
                Destroy(gameObject);
            }
            else
            {
                Instance = this;
            }
            DontDestroyOnLoad(gameObject);
    
            sceneFader = GetComponentInChildren<SceneFader>();
        }
        public void SwitchMana(ManaState _manaState)
        {
            switch (_manaState)
            {
                case ManaState.FullMana:
                    halfMana.SetActive(false);
                    fullMana.SetActive(true);
                    break;
                case ManaState.HalfMana:
                        fullMana.SetActive(false);
                        halfMana.SetActive(true);
                        break;
    
            }
            manaState = _manaState;
        }
        public IEnumerator ActivateDeathScreen()
        {
            yield return new WaitForSeconds(0.8f);
            StartCoroutine(sceneFader.Fade(SceneFader.FadeDirection.In));
            yield return new WaitForSeconds(0.8f);
            deathScreen.SetActive(true);
        }
        public IEnumerator DeactivateDeathScreen()
        {
            yield return new WaitForSeconds(0.5f);
            deathScreen.SetActive(false);
            StartCoroutine(sceneFader.Fade(SceneFader.FadeDirection.Out));
        }
    }
    

    Bonfire:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.SceneManagement;
    
    public class Bonfire : MonoBehaviour
    {
        public bool interacted;
        // Start is called before the first frame update
        void Start()
        {
    
        }
    
        // Update is called once per frame
        void Update()
        {
    
        }
        private void OnTriggerStay2D(Collider2D _collision)
        {
            if(_collision.CompareTag("Player") && Input.GetButtonDown("Interact"))
            {
                interacted = true;
    
                SaveData.Instance.bonfireSceneName = SceneManager.GetActiveScene().name;
                SaveData.Instance.bonfirePos = new Vector2(gameObject.transform.position.x, gameObject.transform.position.y);
                SaveData.Instance.SaveBonfire();
            }
        }
        private void OnTriggerExit2D(Collider2D _collision)
        {
            if (_collision.CompareTag("Player"))
            {
                interacted = false;
            }
        }
    }
    

    SaveData:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System.IO;
    using UnityEngine.SceneManagement;
    
    [System.Serializable]
    public struct SaveData 
    {
        public static SaveData Instance;
    
        //map Stuff
        public HashSet<string> sceneNames;
    
        public string bonfireSceneName;
        public Vector2 bonfirePos;
        public void Initialize()
        {
            if(!File.Exists(Application.persistentDataPath + "/save.bonfire.data"))
            {
                BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.bonfire.data"));
            }
            if (sceneNames == null)
            {
                sceneNames = new HashSet<string>();
            }
        }
        public void SaveBonfire()
        {
            using (BinaryWriter write = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.bonfire.data")))
            {
                write.Write(bonfireSceneName);
                write.Write(bonfirePos.x);
                write.Write(bonfirePos.y);
            }
        }
        public void LoadBonfire()
        {
            if(File.Exists(Application.persistentDataPath + "/save.bonfire.data"))
            {
                using (BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.bonfire.data")))
                {
                    bonfireSceneName = reader.ReadString();
                    bonfirePos.x = reader.ReadSingle();
                    bonfirePos.y = reader.ReadSingle();
                }
            }
        }
    }
    

    GameManager:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.SceneManagement;
    
    public class GameManager : MonoBehaviour
    {
        public string transitionedFromScene;
    
        public Vector2 platformingRespawnPoint;
        public Vector2 respawnPoint;
        [SerializeField] Bonfire bonfire;
    
        public GameObject shade;
    
        public static GameManager Instance { get; private set; }
        private void Awake()
        {
            SaveData.Instance.Initialize();
            if (Instance != null && Instance != this)
            {
                Destroy(gameObject);
            }
            else
            {
                Instance = this;
            }
            SaveScene();
            DontDestroyOnLoad(gameObject);
            bonfire = FindObjectOfType<Bonfire>();
        }
        public void SaveScene()
        {
            string currentSceneName = SceneManager.GetActiveScene().name;
            SaveData.Instance.sceneNames.Add(currentSceneName);
        }
        public void RespawnPlayer()
        {
            SaveData.Instance.LoadBonfire();
            if(SaveData.Instance.bonfireSceneName != null)
            {
                SceneManager.LoadScene(SaveData.Instance.bonfireSceneName);
            }
            if(SaveData.Instance.bonfirePos != null)
            {
                respawnPoint = SaveData.Instance.bonfirePos;
            }
            else
            {
                respawnPoint = platformingRespawnPoint;
            }
            PlayerController.Instance.transform.position = respawnPoint;
            StartCoroutine(UIManager.Instance.DeactivateDeathScreen());
            PlayerController.Instance.Respawned();
        }
    }
    
    #17044
    Terence
    Keymaster

    Managed to fix your problem. The Fader is coming from your UIManager’s entrance animation. I modified your UIManager’s Awake function so that it calls base.Awake() only if it is not destroyed. Otherwise, if you have duplicate UIManagers on the Scene, they will trigger the entrance fade and get destroyed before they are able to clean up the fade animation.

    
    public class UIManager : UIScreen
    {
        public static UIManager Instance; //¨¾¤î¦h­Ó­«½Æªºª±®a¸}¥»¥X²{
    
        [Header("UI Manager")]
        public GameObject mapHandler; //¦a¹Ï
        public GameObject inventory; //­I¥]
        public UIScreen deathScreen;
    
    
    
        protected override void Awake()
        {
            if (Instance != null && Instance != this)
            {
                Destroy(gameObject);
                return;
            }
    
            base.Awake();
    
            DontDestroyOnLoad(gameObject);
            Instance = this; //new
    
        }
    }

    One more thing as well: You don’t need an entrance animation for your UIScreen, because the SceneTransition script already handles the fade in / fade out.

    #17022
    MI NI
    Former Patron

    Yes, my QuitToMainMenu uses UIManager’s LoadScene, but my problem is that the Fader (Temp) will not be deleted when I switch scenes, but the player can still move freely, including using the pause menu, but the screen will be black. (Fader(Temp))

    #16961
    MI NI
    Former Patron

    I encountered a problem again. When I pressed pause, the pause menu would not appear, but it was successfully enabled. I also clicked the button, but there was no screen. When I pressed the continue game button, the pause menu would Fade in and out. Then I tested the button to exit the game, After I press the exit button, the Fader (Temp) object will not return to the main screen. It will not jump to the main menu until I press the pause menu (ESC) again.

    A_DONUT
    Moderator

    Let’s go through each of your issues step-by-step:


    1. Console Error in UIManager:

    The error might be related to how DontDestroyOnLoad() is interacting with other scripts or objects. Ensure the sceneFader component is properly linked, and double-check if your UIManager object exists in the scene hierarchy.

    Potential fixes:

    • Ensure that SceneFader is attached as a child object in the inspector.
    • Check for duplicate UIManager objects when the scene reloads.
    • Add Debug.Log to verify the sceneFader assignment.

    2. Bat Stun Issue:

    Problem: The bat gets stunned even if stunDuration is set to 0 and also gets stunned/knockbacked after dying.

    Fixes:

    • Check stun logic:
      In EnemyHit(), ensure the bat only gets stunned if the stunDuration is greater than zero:

      csharp
      if (health > 0 && stunDuration > 0)
      {
          ChangeState(EnemyStates.Bat_Stunned);
      }
      else if (health <= 0)
      {
          ChangeState(EnemyStates.Bat_Death);
      }
      <code></code>
    • Disable collision after death:
      In Death(), ensure that the bat no longer processes hit logic or collisions:

      csharp
      protected override void Death(float destroyTime)
      {
          base.Death(destroyTime);
          rb.velocity = Vector2.zero; // Stop all movement
          rb.gravityScale = 12;
          GetComponent<Collider2D>().enabled = false; // Disable collisions
      }
      <code></code>

    3. Jumping Too High:

    Problem: The character sometimes jumps too high when you lightly tap the jump button.

    Fix: Adjust the Jump() method to apply a minimum height and reduce velocity more smoothly:

    csharp
    if (Input.GetButtonUp("Jump") && rb.velocity.y > 3)
    {
        rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y * 0.5f); // Reduce, but don't cancel instantly
    }
    <code></code>

    Also, ensure jumpBufferCounter and coyoteTimeCounter are reset correctly after jumps.


    4. Walljumping Issue (Directional Problems):

    Problem: Walljumping works only on the right-side wall correctly.

    Fix: Ensure the walljump direction logic is symmetrical:

    csharp
    if (Input.GetButtonDown("Jump") && isWallSliding)
    {
        isWallJumping = true;
        float jumpDirection = pState.lookingRight ? -1 : 1; // Simplified for clarity
        rb.velocity = new Vector2(jumpDirection * wallJumpingPower.x, wallJumpingPower.y);
        Invoke(nameof(StopWallJumping), wallJumpingDuration);
    }
    <code></code>

    Also, remove any unnecessary transform.eulerAngles adjustments unless flipping visually.


    5. Camera Reset After Scene Transition:

    Problem: Returning to a previous scene doesn’t set the correct camera position.

    Fix: Store the current camera or position before transitioning:

    csharp
    public Vector3 lastCameraPosition;
    
    // Before transitioning scenes
    lastCameraPosition = Camera.main.transform.position;
    
    // After loading the scene, reset the camera
    Camera.main.transform.position = lastCameraPosition;
    <code></code>

    6. Unpause Game with Escape Key:

    Add an Escape key check in your Update() function:

    csharp
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            if (gameIsPause)
            {
                unpauseGame(); // Unpause the game if it's already paused
            }
            else
            {
                // Existing code to pause the game
                pauseMenu.fadeUIIn(fadeTime);
                Time.timeScale = 0;
                gameIsPause = true;
            }
        }
    }
    <code></code>

    These changes should address your issues. Let me know if you need further clarification or have more details to share! 😊

    Terence
    Keymaster

    Can you show me your UIManager, SceneTransition and SceneFader scripts?

    Terence
    Keymaster

    Try adding this line to SceneTransition. That should fix it:

        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;
                if(UIManager.Instance.sceneFader == null)
                    UIManager.Instance.sceneFader = UIManager.Instance.GetComponentInChildren<SceneFader>();
                StartCoroutine(UIManager.Instance.sceneFader.FadeAndLoadScene(SceneFader.FadeDirection.In, transitionTo));
            }
        }

    The problem is likely that UIManager loads after SceneTransition, causing UIManager.Instance.sceneFader to be null and breaking the sceneFader transition.

    tai
    Former Patron

    Here is the SceneFader.cs. It already changed to Awake when i downloaded it.

    <code>using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    using UnityEngine.SceneManagement;
    
    public class SceneFader : MonoBehaviour
    {
        public 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 void CallFadeAndLoadScene(string _sceneToLoad)
        {
            StartCoroutine(FadeAndLoadScene(FadeDirection.In, _sceneToLoad));
        }
    
        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 += 0.02f * (_fadeDirection == FadeDirection.Out ? -1 : 1);
        }
    }
    </code>
    Terence
    Keymaster

    If you are still working on the 9.5 files, try changing the Start() to Awake() in SceneFader and see if it fixes the issue. More information here: https://blog.terresquall.com/community/topic/part-5-article-changes-common-issues-bugfixes/

Viewing 15 results - 1 through 15 (of 94 total)

Advertisement below: