I am trying to develop different ways of navigation. I have a camera mover object which takes it’s position from this bit of code:
var object : Transform;
var offSet = Vector3(0, 0, 0);
function Update () {
if (object) {
object.position = camera.ScreenPointToRay(Input.mousePosition).origin+camera.transform.TransformDirection(offSet);
}
}
The code is attached to the main camera. My idea is to move the camera across the screen by the same amount as the object. So if the object moves left to right by 200px the camera will shift the view by the same amount. I tried parenting the camera to the object but the results are not what I am after. The snippet below works in reverse and not really what I am after. Has anyone got any ideas of how to achieve the effect? Thank you.
if (Input.GetMouseButton (0)){
Camera.main.transform.position.x = object.position.x;
Camera.main.transform.position.y = object.position.y;
}
Um… you can’t move the “camera” across the screen, it is the screen.
If you tell the object that it’s position is 300x300 on a 400x400 screen, this will move the object 100x100. If you then move your camera that amount, then the object is still going to move 100x100 next frame because the mouse is offset that much from the middle.
The only possible way that it could work would be to capture the mouse position after each frame and get the difference. That is Input.GetAxis(“Mouse X”) and Input.GetAxis(“Mouse Y”).
The code you provided would put the object dead center on the near clipping plane. this would cut the model in half. I suppose you want something closer to this:
var object : Transform;
var speed = 2.0;
var distance = 20.0;
function Update () {
if (object) {
var offset = Vector3(Input.mousePosition.x, 0, Input.mousePosition.y);
offset -= Vector3(Screen.width / 2, 0, Screen.height / 2);
object.position += offset * speed * Time.deltaTime;
transform.position=object.position + Vector3.up * distance;
transform.LookAt(object);
}
}
Thanks for the reply. I am working with a touchscreen, but it is an infrared one so can not calculate the pan using my original code which works using Input.GetAxis(“Mouse X”) etc. It works very well with a mouse, but the touchscreen does’ understand mouse axis. That’s why I’m trying different avenues. I want the amount of camera movement to be equal to the length of drag, but can’t get my head around it. I have given up using a surrogate object and just manipulating the camera position. The code below works if I drag at the bottom left of the screen, because that’s where the origin of x and y is. I was hoping to get the distance (difference) between original and second positions and move the camera by that amount. Cheers
Unfortunately the screen doesn’t understand touch input, it only uses mouse emulation, and does that pretty badly too! So I’m stuck searching for workarounds. This is beginning to work… But again, my grasp of math is lacking so I’m not sure what I should be subtracting or adding to what. I have a feeling that knowing the centre of the screen is going to be important so the camera doesn’t “jump” to the new position, but is rather offset by the distance between mouse position. Thanks for your help BigMrB
Okay, this works pretty well. As long as I don’t rotate the camera. The “1000” is an arbitrary number, but without it the pan is way too fast. To sort the rotation issues out, I am guessing I will have to use camera’s translate.up and translate.right so it moves it along the relative X and Y axis. The question remains however… is is possible to link the amount the camera moves to the distance of the drag???
if (GUIControl.menuInt == 5){
if (Input.GetKeyDown ("mouse 0")){
originalPos = Input.mousePosition;
}
if (Input.GetMouseButton (0)){
secondPos = Input.mousePosition;
lastPos = transform.position;
if (originalPos.x < secondPos.x){
transform.position.x = lastPos.x-(secondPos.x - originalPos.x)/1000;
}
if (originalPos.y > secondPos.y){
transform.position.y = lastPos.y+(originalPos.y - secondPos.y)/1000;
}
if (originalPos.x > secondPos.x){
transform.position.x = lastPos.x+(originalPos.x - secondPos.x)/1000;
}
if (originalPos.y < secondPos.y){
transform.position.y = lastPos.y-(secondPos.y - originalPos.y)/1000;
}
}
if (Input.GetKeyUp ("mouse 0")){
lastPos = transform.position;
}
}
}
OK, given that there is no special anything to control it… Yes, this is very simple. You basically want to take the touch point and convert it to world space, then take that point convert it to local space on the camera, make it the same plane as the camera then convert it back to world space.
Lets add one more twist and make it smoothly move from one place to another.
var position : Vector3 = Vector3.zero;
function Start(){
position = transform.position;
}
function Update(){
if (Input.GetMouseButton(0)){
// get the world space of the touch
var touchPos = camera.ScreenToWorldPoint(Input.mousePosition);
// transpose it into local space
touchPos = transform.InverseTransformPoint(touchPos);
// make the touch position the same plane as the camera (not the near clip plane)
touchPos.y=0;
// convert the point back to world space
position = transform.TransformPoint(touchPos);
}
// lerp the position so that it smoothly follows the finger
transform.position=Vector3.Lerp(transform.position, position, 2.0 * Time.deltaTime);
}
I tried implementing your code in my script and also by attaching the code to the camera separately. When just attached to the camera, the result is minimal, but I can see the value change slightly in the editor, so I can see something lerping the x y z values, but not by much.
When implemented inside my code, the camera just “zooms” in to a 0,0,0 point in space, after which the values do not change, no matter where I click or drag.
Thank you for the effort though, I much appreciate it.
lol, thats what I get for not testing it… Sorry, its not ScreenToWorldPoint, its ScreenPointToRay.
I also added some speed to make it a little faster.
var position : Vector3 = Vector3.zero;
var speed : float = 25.0;
function Start(){
position = transform.position;
}
function Update(){
if (Input.GetMouseButton(0)){
// get the world space of the touch
var ray = camera.ScreenPointToRay(Input.mousePosition);
var touchPos = ray.origin;
// transpose it into local space
touchPos = transform.InverseTransformPoint(touchPos) * speed;
// make the touch position the same plane as the camera (not the near clip plane)
touchPos.z=0;
// convert the point back to world space
position = transform.TransformPoint(touchPos);
}
// lerp the position so that it smoothly follows the finger
transform.position=Vector3.Lerp(transform.position, position, 2.0 * Time.deltaTime);
}
After tinkering a little with your script this is the version that works almost perfectly for my needs.
var position : Vector3 = Vector3.zero;
var speed : float = 250.0;
function Update(){
if (Input.GetMouseButton(0)){
// get the world space of the touch
var ray = camera.ScreenPointToRay(Input.mousePosition);
var touchPos = ray.origin;
// transpose it into local space
touchPos = transform.InverseTransformPoint(touchPos) * speed;
// convert the point back to world space (negate it for camera movement)
position = -transform.TransformPoint(touchPos);
// lerp the position so that it smoothly follows the finger
transform.position = Vector3.Lerp(transform.position, position, 2.0 * Time.deltaTime);
}
}
The “speed” variable seems to control the Z position of the camera? I am not sure why that is. The actual transform.position.z seems to be overridden even if I set it. position.z = 0 also has no effect, compared to the speed value.
The second issue that I have is the camera lerps to the starting position of the touch. I need it to only move the distance of the drag. So instead of lerping to the first touch, remain in place until we drag in whatever direction, and then the position of the camera is offset by the distance of the drag. This works EXTREMELY well if my second touch starts where the first one ended, because there is no offset. This is why in my previous version I had to work out the difference between the firstPos and secondPos.
This is really getting there BigMisterB, thank you so much for all your help.