I'm working in unity2d. I have gameobject with co-ordinate and it position and scale perfectly. I want to use that same co-ordinate to UI object instantiate position and scale like normal gameobject in c# script.
void long_tile_func(Vector2 position_,List<int> counter)
{
cam = Camera.main;
Vector2 instantiate_pos = cam.ViewportToScreenPoint(new Vector2(position_.x,position_.y));
instantiate_pos.y=instantiate_pos.y/10f;
instantiate_pos.x=instantiate_pos.x/10f;
GameObject slider_=Instantiate(long_tile,position_,Quaternion.identity) as GameObject;
Vector3 v=new Vector3(5.3f,(Vector3.Distance(obj_1.transform.position,obj_3.transform.position)/4f));
slider_.transform.localScale=v;
slider_.transform.SetParent(GameObject.FindGameObjectWithTag("background").transform,false);
}
I tried to convert co-ordinate to screenpoint with this function cam.ViewportToScreenPoint(). But it isn't work as much i expect..
Related
How to make a plane to "look" at the camera by rotating on only on one axis?
For example, I have a plane with a texture of smoke coming from the pipe. If I walk around the pipe the plane should always be facing the camera, rotating along the y axis. But the direction of the smoke should not change, therefore, along with the x and z axes, the plane should not rotate.
Here is a code example which helps to rotate the plane on all axes:
void Update()
{
transform.LookAt(Camera.main.transform.position, -Vector3.up);
}
How to make it rotate only on one axis?
One approach to this is to store the object's original rotation in a Vector3 using transform.eulerAngles. You can then create another Vector3 to store the object's rotation after the LookAt function has completed. You can then set the object's rotation to a new Vector3 using only the y value from the second variable and using the original x and y values. It would look something like this:
void Update()
{
Vector3 originalRotation = transform.eulerAngles;
transform.LookAt(Camera.main.transform.position, -Vector3.up);
Vector3 newRotation = transform.eulerAngles;
transform.eulerAngles = new Vector3(originalRotation.x, newRotation.y, originalRotation.z);
}
I have a GameObject named Player, and a Canvas. The HealthBar GameObject is a child of the Canvas (Canvas>HealthBar). I have the HP bar following the player with a script. It is supposed to follow the player at a fixed position above it, so it sits near the top of the sprite.
Here is the 'follow' part of the HP Follow Script.
void Update ()
{
Vector3 currentPos = transform.position;
Vector3 playerPos = Camera.main.WorldToViewportPoint (Player.transform.position);
transform.position = playerPos;
The problem is that the HP bar moves with the character, but at a very small fraction of the speed of which the player is moving. For example, if the player moves one unit, the bar moves 0.1 units.
Video of error: https://streamable.com/vaz7h
You want to make a UI Object(Image) follow a GameObject is a SpriteRenderer or MeshRenderer.
In another way, this can be described as converting world point to UI point.
This simple function below converts world position to UI space. It takes a the Canvas of the UI as parameter then the position you want to convert to UI position which in your case is the Player.transform.position variable.
The key for moving a UI object is the RectTransformUtility.ScreenPointToLocalPointInRectangle function which converts the screen point to ui rectangle local point.
public Vector3 worldToUISpace(Canvas parentCanvas, Vector3 worldPos)
{
//Convert the world for screen point so that it can be used with ScreenPointToLocalPointInRectangle function
Vector3 screenPos = Camera.main.WorldToScreenPoint(worldPos);
Vector2 movePos;
//Convert the screenpoint to ui rectangle local point
RectTransformUtility.ScreenPointToLocalPointInRectangle(parentCanvas.transform as RectTransform, screenPos, parentCanvas.worldCamera, out movePos);
//Convert the local point to world point
return parentCanvas.transform.TransformPoint(movePos);
}
Usage:
public GameObject Player;
public Canvas canvas;
void Update()
{
//Convert the player's position to the UI space then apply the offset
transform.position = worldToUISpace(canvas, Player.transform.position);
}
Now, let's say that you have already positioned the UI to be where it is supposed to be and you now want it to follow another Object(Player), you need to implement a simple offset with the code above. This is really easy. Below is what it is supposed to look like:
public GameObject Player;
public Canvas canvas;
Vector3 Offset = Vector3.zero;
void Start()
{
Offset = transform.position - worldToUISpace(canvas, Player.transform.position);
}
void Update()
{
//Convert the player's position to the UI space then apply the offset
transform.position = worldToUISpace(canvas, Player.transform.position) + Offset;
}
public Vector3 worldToUISpace(Canvas parentCanvas, Vector3 worldPos)
{
//Convert the world for screen point so that it can be used with ScreenPointToLocalPointInRectangle function
Vector3 screenPos = Camera.main.WorldToScreenPoint(worldPos);
Vector2 movePos;
//Convert the screenpoint to ui rectangle local point
RectTransformUtility.ScreenPointToLocalPointInRectangle(parentCanvas.transform as RectTransform, screenPos, parentCanvas.worldCamera, out movePos);
//Convert the local point to world point
return parentCanvas.transform.TransformPoint(movePos);
}
If the canvas is ScreenSpace, you can use:
healthbarTransform.position = camera.WorldToScreenPoint(playerTransform.position);
(if it is screen space, it can be child of player or whatever as long as you set the position every frame)
.... About your problem, there are some factors that will solve the issue:
You are setting the healthbar position in the update function, to let unity know to execute this code after player moves for sure, you need to add HPFollow script to below Default time in the script execution order (if you want to use Update).
Or you can use lateUpdate to set the ui positions. which I highly recommend.
If your problem is just flickering ui, it should be about ui rect transform scales...
Here's the solution:
void Start () {
Canvas.willRenderCanvases += canvasUpdate;
}
void canvasUpdate () {
var screenPoint = RectTransformUtility.WorldToScreenPoint( canvas.worldCamera, worldPoint );
Vector2 localPoint;
RectTransformUtility.ScreenPointToLocalPointInRectangle( canvas.GetComponent<RectTransform>(), screenPoint, canvas.worldCamera, out localPoint );
transform.localPosition = localPoint;
}
I want to restrict player movement in the sphere, the schematic diagram show as below. If player movement is out of range, then restrict player to sphere max radius range.
How can I write C# code to implement it, like this?
These are my current steps:
Create 3D sphere
Create C# code append to sphere object
My code so far:
public Transform player;
void update(){
Vector3 pos = player.position;
}
I don't know how you calculate your player`s position but before assigning the new position to the player you should check and see if the move is eligible by
checking the new position distance form the center of the sphere
//so calculate your player`s position
//before moving it then assign it to a variable named NewPosition
//then we check and see if we can make this move then we make it
//this way you don't have to make your player suddenly stop or move it
//back to the bounds manually
if( Vector3.Distance(sphereGameObject.transform.position, NewPosition)< radius)
{
//player is in bounds and clear to move
SetThePlayerNewPosition();
}
What #Milad suggested is right but also include the fact you won't be able to "slide" on the sphere border if your movement vector even slightly goes outside the sphere :
(sorry for the crappy graphic skills...)
What you can do if you want to be able to "slide" on the sphere interior surface is get the angle formed between the player position and the X vector and then apply this angle with the :
public Transform player;
public float sphereRadius;
void LateUpdate()
{
Vector3 pos = player.position;
float angle = Mathf.Atan2(pos.y, pos.x);
float distance = Mathf.Clamp(pos.magnitude, 0.0f, sphereRadius);
pos.x = Mathf.Cos(angle) * distance;
pos.y = Mathf.Sin(angle) * distance;
player.position = pos;
}
Just make sure using this won't counter effect your player movement script (that's why I put it in LateUpdate() in my example).
In my unity 5.3 2D project I have a sprite that uses a vector3 lerp function to move from one location to another on the x axis.But for some reason my map which contains colliders in a maze format causes the sprite to collide with an unknown object and therefore it rotates. I have tried fixing the colliders and seeing if it was any other gameobject that caused the collision but as far as I know a collider is causing the problem. The sprite is able to fit perfectly between colliders but after a some time this problem occurs. Any help would be appreciated.
private Vector3 pos1 = new Vector3(360,166,0);
private Vector3 pos2 = new Vector3(656,166,0);
public float speed = 1.0f;
void Update() {
transform.position = Vector3.Lerp (pos1, pos2, (Mathf.Sin(speed * Time.time) + 1.0f) / 2.0f);
}
Working on a multiplayer game in Unity3D. Like many others, I've got some serious issues getting the camera to follow the player. In a normal game, you simply make the camera object a child of the player object to make it follow the player. In multiplayer, this is not an option as players need to spawn (prefab).
So instead you need to use C# to make the camera follow the player using the player objects transform position. This is what I've tried:
public Transform target;
public float smoothing = 5f;
Vector3 offset;
public GameObject playerPrefab;
private void SpawnPlayer()
{
Network.Instantiate(playerPrefab, Vector3.up * 5, Quaternion.identity, 0);
offset = transform.position - target.position;
}
void LateUpdate()
{
Vector3 targetCamPos = target.position + offset;
transform.position = Vector3.Lerp(transform.position, targetCamPos, smoothing * Time.deltaTime);
}
Ofcourse I've assigned the player prefab to target. So when the game starts, the cameras position is transformed to the players position. But after that, it refuses to follow the player. It just sits there.
So I've started debugging this with:
Debug.log(target.position);
It returns the starting location of the player, but doesn't get updated as the player moves around. It remains the same. So that's obviously the reason the camera won't follow the player.
The question is: Why doesn't the player position get updated? Or most likely it does, but the script doesn't see it. What am I doing wrong?
According to your comments,here is your problem.
When you drag the prefab you assign the transform of the prefab. The player is actually an instance of the prefab (a clone) but not the prefab itself.
You need to create the new object and assign its transform to it.
GameObject player = (GameObject)Network.Instantiate(playerPrefab, Vector3.up * 5, Quaternion.identity, 0);
target = player.transform;
offset = transform.position - target.position;