Problem converting the mouse pos to W using camera.ScreenToWorldPoint()

Hello, I’m having a problem converting the X coord of the Input.mousePosition with the ScreenToWorldPoint.
My grid is ok. It’s a 9x5 unit grid that is working fine placing the attackers and defenders by typing their position in the previous lessons and etc.

When I did the challenge of printing the World Unit coords of the OnMouseDown, I was getting the correct Y coord but a strange X coord. Trying to figure out why, I noticed that in the Game Tab, the height of the Camera was exactly the same of the Level Canvas, but the width was bigger. That was happening because I was setting the Game Tab with Free Aspect.

So, I changed the Game Tab to a 16:9 aspect ratio expecting to work. The camera was exactly like the Level Canvas now but I was still getting strange X coords. But now it was different coords from when Free Aspect was set.

Than, I removed the DefenderSpawner.cs from the Core Game, and with the Game Tab already set to 16:9, I added the script again. I don’t know why but this time it worked!!!

I changed the Game Tab to a 4:3 aspect ratio expecting to still work, but it didn’t work!

I came back to the video and noticed that Ben is still using a Free Aspect Ratio until this point of the section but he didn’t got this error.

Even though I’m getting correct coords now, I’m pretty sure something is wrong here, because it was supposed to work with a 4:3 screen and because the Free Aspect didn’t caused problems to Ben.

Thanks!!

1 Like

It seems something’s wrong with the Camera you’re using in the script, I say this because of the strange “fix” you got by removing the script from the Core Game object and then putting it back in, removing it breaks all references of public variables.

Can you post the DefenderSpawner script, the Core Game full inspector and the Game Camera Inspector (which I guess you’re using inside DefenderSpawner.cs)?

Without these starting info, it’s very, very hard to guess where the problem is. :wink:

2 Likes

Thanks for the suport Galandil! Here you go:

public class DefenderSpawner : MonoBehaviour {

public Camera myCamera;

private GameObject parent;

void Start(){
	parent = GameObject.Find ("Defenders");
	if (parent == null){
		parent = new GameObject("Defenders");
	}
}

void OnMouseDown(){
	
	GameObject newDef = Instantiate (Button.selectedDefender, SnapToGrid(CalculateWorldPointOfMouseClick()), Quaternion.identity) as GameObject;
	newDef.transform.parent = parent.transform;
}

Vector2 SnapToGrid(Vector2 rawWorldPos){
	float newX = Mathf.RoundToInt (rawWorldPos.x);
	float newY = Mathf.RoundToInt (rawWorldPos.y);
	return new Vector2(newX, newY);
	
}

Vector2 CalculateWorldPointOfMouseClick(){
	float mouseX = Input.mousePosition.x;
	float mouseY = Input.mousePosition.y;
	float distanceFromCamera = 11f;
	
	Vector3 weirdTriplet = new Vector3(mouseX, mouseY, distanceFromCamera);
	Vector2 worldPos = myCamera.ScreenToWorldPoint(weirdTriplet);
	
	
	return worldPos;
}

}

A tip for Start(), you can reduce it to a one-liner, like this:

void Start(){ if (parent == null) parent = new GameObject("Defenders"); }

and just delete the Defenders game object from the Hierarchy, you’ll create it programmatically at runtime.

Regarding your problem, your code seems fine to me, I used it on my script and it worked flawlessly in every aspect ratio.

Try this and tell me what happens, privatize the myCamera reference using this line:

instead of your public Camera myCamera. Remember to re-assign the reference in the script field in the Inspector of course.

Can you elaborate, too, regarding the odd readings you had when using Input.mousePosition? If you use 4:3 and try to debug.log the mousePosition in Update(), what readings do you get in the lower left and upper right corner of the game window?

2 Likes

Hi Galandil, thanks for helping me trying to figure this outt!

I tried the SerializeField but the problem persist. I tried to make some screen shoots with hopely helpful debug.logs…

Here a screen shoot with the aspect rate of the game in 16:9 and everything happening as it is supposed to be. The 4 Cactus was placed clicking in the middle of the square of each corner. I left the Debug.Log without the number rounded but they are placed snaped to the grid:

Here is a screen shoot after changing the aspect rate of the game to 4:3, and clicking in the same points… The cactus are placed outside the core game and their X coords are wrong as you can see in the logs:

Here a screen shoot showing the cactus outside the core game even though I clicked in the square inside the core game:

In the Aspect Rate of 4:3, If I click in the middle of each of the 9 squares of line 1, I get these Logs:

I found out what was the problem!! but don`t know why it was not working the way I did before…

You were right! In some way, the problem was the Camera. I prefabed the Camera and I was dragging the prefab to the DefenderSpawner.cs. Instead, I dragged the actual Camera and it worked fine!

Someone can explain why I can`t drag the camera prefab to the script since it is a good practice to link prefabs instead of instances?

Thanks a lot!

1 Like

I’m glad you solved the problem in the end.

And I’m glad you gave me an opportunity to learn something new, too!

Since I wanted to answer your last question, I managed to recreate the exact same strange behaviour you had, by feeding the camera prefab to the script instead of the hierarchy one.

So, without bothering you all with the details of my tests, I’ll skip to the end result.

Every camera has, among others, three fields: pixelWidth, pixelHeight and aspect (these fields are NOT shown in the Inspector in the Camera component). Ofc, pixelWidth and pixelHeight (read only) store the respective values of the camera and, in particular, I noticed that these values change not only in the hierarchy camera (if we change, say, the aspect ratio in the Game window or just resize it), but even in the prefab camera.

Aspect? Not so much, it changes automatically only in the hierarchy camera after any kind of resize, but it stays the same in the prefab camera, and this value is the same one that the hierarchy camera had the last time the prefab was updated with the Apply button.

So, this is what happened to you: when you last updated the camera prefab, you had a 16:9 ratio in the game window, so the camera.aspect field had in that moment the 1.77777 value. And you got stuck to that value since you used the prefab camera in the script, even if you changed at runtime the aspect ratio of the game window.

So, one solution is to just feed the hierarchy camera so that the camera.aspect field is updated automatically by Unity, or, and yes there’s another way, is to update the aspect ratio from script using the camera.ResetAspect() method, which updates the aspect based on the actual pixelWidth and pixelHeight fields (ofc, this solution needs a reference to the camera used in the script, particularly if it’s a prefab camera, and the right moment to call ResetAspect, for example by checking the width and height and call a reset only if one of these two values change at any moment).

Nice learning moment here, I have to say. :smiley:

7 Likes

WOW!!
Thank you so much for this detailed explaination! I think I would be suck in this issue forever if it weren`t you!
Glad that it was useful for you too somehow :stuck_out_tongue:

1 Like

I wish this kind of arcane hidden knowledge was easier to find or search for in the docs, based on the symptoms.

I had the same problem, following the generally sound advice to “work on the prefabs” I dragged the Prefab Camera into the Prefab Core Game myCamera field.

Then I noticed that the Hierarchy Core Game myCamera field didn’t update, so I did a Revert on the Hierarchy Core Game, and the myCamera field filled in and I thought I was good to go.

All I had accomplished was to put the Prefab Camera into the Hierarchy Core Game.

ack! Who knew that this was a Bad Thing! I never would have figured this out on my own.

Had this exact issue, dragging prefab to the core game script.
So this thread is still helping people months later, thanks!

I’m having exactly this strange behavior. I’ll try to understand what’s happening and to solve it, but for now I can’t instatiate the new defenders at exact clicked place.

I’ve followed your previous steps but what I get is this:
screenToWorldUnitsError

I’ve tried to change camera, canvas, script, objects, prefabs, and I don’t know what to do. I re-followed all steps on the course, as Rick does in the videos, but I’m stuck here and I don’t know how to continue.

The four corners of the clickable area draw a perfect 1x1 square, although the size of this area is 5x7, it have no sense to me. xD

Hey there! I’ve solved this! What a mess!

Visual Studio Code made me a trick modifying ScreenToWorldPoint to ScreenToViewportPoint when I was typing, so Unity was doing exactly what I was asking… that’s crazy!!!

This topic was automatically closed after 4 hours. New replies are no longer allowed.

Privacy & Terms