Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

JRPG Battle Transition Effect

Discussion in 'Image Effects' started by Falcoshin, Jan 12, 2019.

  1. Falcoshin

    Falcoshin

    Joined:
    May 31, 2017
    Posts:
    168
    I'm hoping to make one particularly in line with the one from Final Fantasy VII, but I don't even really know where to even begin with something like this. The closest I can think of is a shader that effects the entire screen, but I'm absolutely awful with shader language and am hoping there's an easier method.

    I'd upload a video to show what I want, but for whatever reason the forum won't let me post it.
     
  2. ifurkend

    ifurkend

    Joined:
    Sep 4, 2012
    Posts:
    350
    I'm bored so I just try to replicate it quickly. In short you capture a render texture, assign it to a material and assign it to a particle system. Using the particle system doesn't yield good performance (edit: particularly bad for mobile because of huge area of high transparent overdraw, the particle system itself is fast), but it's easier for you to change the animation without any scripting.



    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class FF7Transition : MonoBehaviour {
    6.  
    7.     [SerializeField,Tooltip("The Main Camera.")] Camera _mainCamera;
    8.     [SerializeField,Tooltip("The Camera which capture the source Render Texture.")] Camera RTCamera;
    9.     [SerializeField,Tooltip("The Camera which renders the result.")]
    10.     Camera RTResultCamera;
    11.  
    12.     [SerializeField,Tooltip("The Particle System which controls the transition animation.")] ParticleSystem _particleSystem;
    13.     private ParticleSystem.MainModule _psm_main;
    14.  
    15.     [SerializeField,Tooltip("The Material which is assigned the Render Texture.")] Material transitionMaterial;
    16.  
    17.     [SerializeField,Tooltip("How much the Render Texture dimension is divided. The greater value will drop the image quality in exchange for performance."),Range(1,8)]
    18.     int downsampling = 2;
    19.  
    20.     [SerializeField,Tooltip("For previewing resultant Render Texture only. Do not change this value.")]
    21.     RenderTexture rtSource;
    22.  
    23.     [SerializeField,Tooltip("For previewing screen width value only. Do not change this value.")]
    24.     double width;
    25.     [SerializeField,Tooltip("For previewing screen height value only. Do not change this value.")]
    26.     double height;
    27.  
    28.     void Awake () {
    29.         if (_mainCamera == null) {
    30.             _mainCamera = Camera.main;
    31.         }
    32.         if (RTCamera == null) {
    33.             RTCamera = this.GetComponent<Camera>();
    34.         }
    35.         if (_particleSystem == null) {
    36.             _particleSystem = this.GetComponent<ParticleSystem>();
    37.         }
    38.         _particleSystem.Stop();
    39.         _psm_main = _particleSystem.main;
    40.    
    41.         RTCamera.enabled = false;
    42.         RTResultCamera.enabled = false;
    43.    
    44.         width = Screen.width;
    45.         height = Screen.height;
    46.    
    47.         float fov = 0.5f / Mathf.Tan(RTResultCamera.fieldOfView * 0.5f * Mathf.Deg2Rad);
    48.         if (width > height) {
    49.             transform.localPosition = new Vector3 (0f, 0f, fov);
    50.             _psm_main.startSizeXMultiplier = (float)(width/height * 1);
    51.             _psm_main.startSizeYMultiplier = 1f;
    52.         } else if (height > width) {
    53.             float hwRatio = (float)(height / width);
    54.             transform.localPosition = new Vector3 (0f, 0f, fov * hwRatio);
    55.             _psm_main.startSizeXMultiplier = 1f;
    56.             _psm_main.startSizeYMultiplier = hwRatio * 1f;
    57.         }
    58.     }
    59.  
    60.     void OnEnable () {
    61.         int _width = (int)(width / downsampling);
    62.         int _height = (int)(height / downsampling);
    63.         rtSource = RenderTexture.GetTemporary(_width, _height, 16, RenderTextureFormat.Default);
    64.    
    65.         RTCamera.targetTexture = rtSource;
    66.         RTResultCamera.depth = 100f;
    67.    
    68.         transitionMaterial.SetTexture("_MainTex", rtSource);
    69.    
    70.         RTCamera.Render();
    71.         RTResultCamera.enabled = true;
    72.         _particleSystem.Play();
    73.    
    74.         StartCoroutine("DisableMainCamera");
    75.     }
    76.  
    77.     IEnumerator DisableMainCamera() {
    78.         yield return new WaitForSeconds(0.35f);
    79.         _mainCamera.enabled = false;
    80.         yield return null;
    81.     }
    82.  
    83.     void OnDisable () {
    84.         StopAllCoroutines();
    85.         RenderTexture.ReleaseTemporary(rtSource);
    86.         RTResultCamera.enabled = false;
    87.         _mainCamera.enabled = true;
    88.         _particleSystem.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
    89.     }
    90. }
     

    Attached Files:

    Last edited: Jan 30, 2019
    Pandur1982 likes this.
  3. Falcoshin

    Falcoshin

    Joined:
    May 31, 2017
    Posts:
    168
    Yeah, someone else told me the same method, but I'm having trouble following the code. If you'll permit me, I'd like to ask about how it works in depth.

    To start with, should I assume that the line
    Code (csharp):
    1. rtSource = RenderTexture.GetTemporary(_width, _height, 16, RenderTextureFormat.Default);
    gets a screenshot of the current frame and stores it as a texture? Because I was told that was the first step in making this work.
     
  4. ifurkend

    ifurkend

    Joined:
    Sep 4, 2012
    Posts:
    350
    Yes it is. I forgot to add RenderTexture.ReleaseTemporary(rtSource); at the end.
     
  5. Falcoshin

    Falcoshin

    Joined:
    May 31, 2017
    Posts:
    168
    So what differentiates this line of code from the ScreenCapture.CaptureScreenshotAsTexture() method that I found in the Unity docs?
     
  6. ifurkend

    ifurkend

    Joined:
    Sep 4, 2012
    Posts:
    350
    Never used ScreenCapture, but from the API it seems to have some limitation like excluding the UI objects. RenderTexture gives you the flexibility of choosing what to include in your screenshot by manipulating the RT capturing camera culling mask.

    In case you haven’t yet, the unitypackage in my first reply has a scene file demonstrating the usage.
     
    Last edited: Jan 15, 2019
  7. Falcoshin

    Falcoshin

    Joined:
    May 31, 2017
    Posts:
    168
    It's not excluding the UI objects, but it is doing something weird. I'm trying to display the screenshot on a UI panel and it looks like this:

    Capture 2.PNG

    When it should look like this:

    Capture.PNG

    Is there a reason this might be happening?
     
  8. ifurkend

    ifurkend

    Joined:
    Sep 4, 2012
    Posts:
    350
    This thread on Answers might help. But it seems you haven't defined the correct width and height from Screen.width and Screen.height.
     
  9. Falcoshin

    Falcoshin

    Joined:
    May 31, 2017
    Posts:
    168
    Ok, so I think I fixed the problem. It's that I didn't set up a coroutine that (I think) waited for the end of the frame. However, I'm not sure why that would make a difference. The way the docs made it sound, waiting to the end of the frame was to make sure UI elements would be in the screenshot. So why would the lack of a coroutine cause THIS?