Move Game Object to UI after collision (like Psychonauts figments)

I want to make something very similar to the way figments work in Psychonauts. For context: they’re basically 2D images you pick up on collision, after which they’re moved to the corner of your screen so you can see which figment you picked up last.

The “figments” in my game are planes in 3D space that always face the camera, and right now when you pick them up a counter goes up and the object gets destroyed. This is fine, but I want to try something flashier. When the player collides with the object, I want it to move to the bottom right corner of the UI canvas. Extra challenge: when a new figment is picked up, the previous one (the one that’s on screen in the UI) should be destroyed.

None of this is important by the way, I could stick with a counter and it’ll be fine, but it’s a fun challenge and my Googling seems to have reached its limit!

Here are the relevant code snippets:

The collecting script, attached to the Player:

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

public class figmentCollect : MonoBehaviour
{
    public int score;
    public TMP_Text scoreCounter;
		
	void OnTriggerEnter(Collider other)
	{
    	if (other.tag == "Figment")
    	{
       		score += 1;
       		Destroy(other.gameObject); //I understand this has to go, of course
    	}
	}

	void Update()
    {
        scoreCounter.SetText(score.ToString());
    }
}

The score counter, attached to the GUI Canvas:

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

public class scoreCount : MonoBehaviour
{
	public int score;
	public TMP_Text scoreCounter;

    void Update()
    {
        scoreCounter.SetText(score.ToString());
    }
}

The GUI Canvas also has a DontDestroyOnLoad script attached. All the code above works flawlessly.

And here is the code I’ve been fiddling with to get the image to move to the UI:

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

public class figmentImageMover : MonoBehaviour
{
	public GameObject Player;
    public GameObject FigmentImage; //disabled UI image, used to provide the position transform information
    public GameObject collectedFigment; //

    void Start(){
    	collectedFigment = Player.GetComponent<figmentCollect>();
    }

    void FixedUpdate()
    {
    	Vector3 screenPoint = FigmentImage.transform.position;
    	Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPoint);
    	collectedFigment.transform.position = Vector3.MoveTowards(FigmentImage.transform.position, worldPos, currentMoveSpeed);
    }
}

This is nonsense, because it refers to variables I’ve since removed to get back to the simple counter state, but maybe it’ll provide some insight :^)

Some thoughts for workarounds:

  • Instead of moving the collided object itself, create/enable an image object with the same texture as the specific figment. Maybe even have one single image in the UI and just change its material to correspond with the latest collected figment. Is that possible?
  • Manage to mush some of these scripts together, so I won’t have to refer to variables between scripts
  • That’s about it, I’m very new to Unity lmao

I got one of the workarounds working! What I did was:

  • Add a Raw Image object to my UI
  • In the figmentCollect script, change the material of the Raw Image to the material of the collided object
  • Change the color of the Raw Image to white, this is so I could start the game with the image being transparent. This part only needs to happen once, but I don’t think it will add that much load when calling it for every figment.

Here is the updated code in case anyone is trying to do the same:

public class figmentCollect : MonoBehaviour
{
    public int score;
    public TMP_Text scoreCounter;
    public GameObject figmentMaterial;
		
	void OnTriggerEnter(Collider other)
	{
    	if (other.tag == "Figment")
    	{
       		score += 1;
       		figmentMaterial.GetComponent<RawImage>().material = other.gameObject.GetComponent<MeshRenderer>().material;
       		figmentMaterial.GetComponent<RawImage>().color = new Color(1, 1, 1, 1);
       		Destroy(other.gameObject);
    	}
	}

	void Update()
    {
        scoreCounter.SetText(score.ToString());
    }
}