0
\$\begingroup\$

I'm currently trying to achieve an effect like this, except wirh a 3D character:

enter image description here

I've tried a variety of of techniques but have fallen short, I feel like I'm on the right track but just missing something. Here's the steps I tried to take:

  • Get the distance between my current player position and previous position and if its greater than some arbitrary number I call the Render() method on my second camera that only renders the player

  • In the OnRenderImage() function I then use Graphics.Blit() to copy the contents of my render texture to my main cameras image

  • Second camera then renders that view to a RenderTexture which is sent to a script on my Main Camera

Here is the script on my player character:

public class AfterImageTest : MonoBehaviour
{
    private Vector3 prevPos;

    private float Speed = 40;
    [SerializeField] private GameObject _camera;
    private float dt;
    private float a = 0;
    // Start is called before the first frame update
    void Start()
    {
        prevPos = this.transform.position;
    }

    // Update is called once per frame
    void Update()
    {
        if (dt >= 0.1f)CreateSnapShot();
        Vector3 currentPos = transform.position;
       
        currentPos.y += Mathf.Sin(a ) * Speed * Time.deltaTime;
        transform.position = currentPos;
        dt = Vector3.Distance(prevPos,currentPos);
        prevPos = currentPos;
        a += 0.1f;
    }


    void CreateSnapShot()
    {
        Debug.Log("Capturing screenshot");
        _camera.SetActive(true);
        _camera.GetComponent<Camera>().Render();
        _camera.SetActive(false);
    }
}

And here is the script on my Main Camera:

public class AfterImage : MonoBehaviour
{
    public RenderTexture rt1;
    
    void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        // Blit the contents of camera2's render texture to the destination texture
         Graphics.Blit(source,rt1);
         Graphics.Blit(rt1, destination);
    }
}

Some other things to note:

  • I have the depth value of my second Camera set to -1 and my depth value set to 0 to make sure they are rendered in the correct order

  • I have made sure the render texture I'm outputting to has transparency enabled (if you look at the render texture it only contains the character and a black background)

All I see when I do this is the main camera's viewpoint and no indication the render texture has been applied to my main camera's render. Any help would be greatly appreciated!

Also it's important to note, my game is in 3D not 2D so using particle effects to copy the player sprite isn't possible.

\$\endgroup\$
0

1 Answer 1

0
\$\begingroup\$

So after trying a few different approaches I finally found one that achieved the desired effect using the SkinnedMeshRenderer component. Here is the code:

public class AfterImageTest : MonoBehaviour
{
    [SerializeField]private SkinnedMeshRenderer[] _skinnedMeshRenderers;
    
 
    void Start()
    {
        _skinnedMeshRenderers = GetComponentsInChildren<SkinnedMeshRenderer>();
        for ( int j = 0; j < _skinnedMeshRenderers.Length; j++)
            {
             
                    GameObject obj = new GameObject();
                    obj.transform.SetPositionAndRotation(this.transform.position, this.transform.rotation);
                    //obj.transform.Rotate(new Vector3(0,0,0));
                    MeshRenderer meshRenderer = obj.AddComponent<MeshRenderer>();
                    MeshFilter meshFilter = obj.AddComponent<MeshFilter>();
                    Mesh mesh = new Mesh();
                    _skinnedMeshRenderers[j].BakeMesh(mesh);
                    meshFilter.mesh = mesh;
                    meshRenderer.materials = _skinnedMeshRenderers[j].materials;
        }
    }
 
 
}

The last line meshRenderer.materials = _skinnedMeshRenderers[j].materials; is important if your character has more than one material applied to it! Otherwise unity will simply pick the first material on the list of materials and youll find parts of your mesh missing. If you only have one material you can do:

meshRenderer.material = _skinnedMeshRenderers[j].material;

Hope this helps!

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .