- Home /
Cinemachine 2D Level Wrap
Hello,
I'm new to Unity and I'm trying to create a 2D shoot ’em up game. I got one level and I want to create a seamless horizontal wrap effect. I decided to implement the effect with 2 duplications of my level, each on one side. I created the sprites so that they merge seamlessly into each other.
For the camera movement I'm using cinemachine. My virtual camera is following my player. Futhermore I added a confiner to the virtual camera to keep the camera record my level. The bounding shape of the confiner is set to the whole level included the duplicates on the sides.
On the ends of my main level instance, I placed two 2D BoxColliders. When the Player enters a BoxCollider it is teleported to the opposite side. Here is my script, which is added to the colliders:
using Cinemachine;
using UnityEngine;
public class WorldWrapper : MonoBehaviour
{
public GameObject player;
public CinemachineVirtualCamera vCam1;
private CinemachineComponentBase _myCamera;
private void Start()
{
_myCamera = vCam1.GetCinemachineComponent<CinemachineComponentBase>();
}
private void OnTriggerEnter2D(Collider2D other)
{
Vector3 playerPos = player.transform.position;
Vector3 camPos = vCam1.transform.position;
if (player)
{
player.transform.position = new Vector3(-playerPos.x, playerPos.y, playerPos.z);
Vector3 positionDelta = new Vector3(-camPos.x - camPos.x, 0, 0);
_myCamera.OnTargetObjectWarped(player.transform, positionDelta);
}
}
This is working but, I got a problem with the camera positioning on players teleport. After the the player is teleported, the camera is not showing the exact picture of the level as before. The camera is a little bit offset, that's why the wrap is noticeable.
Currently I have no idea how to fix the camera position so the wrap isn't noticeable. I would be pleased about solution suggestions.
Update
I think I figured out my problem. It's not a probelm of the camera or of the script. It is a error in my reasoning. The teleport collider does not have to teleport the player to the opposite side of the main level. It has to teleport to player to the end of the opposite level duplication, which is adjacent to the main level.
For better unterstanding I created a sketch of my problem:
I think this will cause a problem with the current positions of my teleport colliders. What is the best way to solve this problem?
That makes sense. Reposition your colliders to the correct spots. Or if you have an actual strip of levels like that, maybe create a gap between them for the collider to reside in.
Ok, thanks. I went for moving the player by the world size. Also I repositionated the colliders. Now it's working.
Great. I've added my comment to the answer below since it completes the solution to your issue
Answer by icehex · Apr 30, 2020 at 12:54 AM
Edit: That makes sense. Reposition your colliders to the correct spots. Or if you have an actual strip of levels like that, maybe create a gap between them for the collider to reside in.
For the script to work correctly if your camera and player do not have the exact same X coordinate --- positionDelta is meant to be the target's position change. https://docs.unity3d.com/Packages/com.unity.cinemachine@2.1/api/Cinemachine.ICinemachineCamera.html
Try:
using Cinemachine;
using UnityEngine;
public class WorldWrapper : MonoBehaviour
{
public GameObject player;
public CinemachineVirtualCamera vCam1;
private CinemachineComponentBase _myCamera;
private void Start()
{
_myCamera = vCam1.GetCinemachineComponent<CinemachineComponentBase>();
}
private void OnTriggerEnter2D(Collider2D other)
{
Vector3 playerPos = player.transform.position;
Vector3 camPos = vCam1.transform.position;
if (player)
{
player.transform.position = new Vector3(-playerPos.x, playerPos.y, playerPos.z);
Vector3 positionDelta = new Vector3(-playerPos.x - playerPos.x, 0, 0);
_myCamera.OnTargetObjectWarped(player.transform, positionDelta);
}
}
Here's what I'm seeing in my head:
Thanks for your suggestion. I already tried that before I posted my question, but it had no effect to my problem. It doesn't matter if I calculate the cameras or players position change. The problem still remains, that on the right bound, when the player is in front oft the collider the camera shows more of the left level terrain. On the left side it's exactly the opposite, the camera shows more of the right level terrain. That's why the wrap is noticeable. But the camera and the player are correctly teleported to the exact opposite position. Nevertheless camera is not showing the same picture.
That's interesting because the behavior you describe observing is what using -2*(camPos.x) would give you, but not -2*playerPos.x, with the assumption that your camera and player are not on fixed to the same x coordinate to begin with. I couldn't add an image to my comment here so I uploaded it to my answer above to show you what I'm thinking. Are the player and the camera at the same X coordinate at all times?
I checked the source code for Cinemachine and the behavior of OnTargetObjectWarped is that it will add the positionDelta to the camera's current or last frame position, depending on which camera options you're using. So only other possibility I can think of at the moment is that you're using a camera option that puts you 1 frame behind somehow.
Yes, the player and the camera are on the same X coordinate all the time. I also updated my question. I realized that it's a problem with the position where the player is moved. But currently I have no idea how to fix it. What is the best way to handle it? Creating connected portals?
Your answer
Follow this Question
Related Questions
How to create a multilayered 2D effect? 1 Answer
Cinemachine camera shake on button press 0 Answers
Unity 3D Render Camera Bug!!! 1 Answer
Scale game vertically only 0 Answers
Making main camera focus on trigger 1 Answer