Unity3d Linerenderer not visible - unity3d

I am trying to draw a line between two UI GameObjects with Linerenderer. In scene mode everything work fine, but in game mode line is invisible. I tried to change Z position of objects but lines are still invisible. Can anyone help me? Thanks in advance
private LineRenderer lineRenderer;
private float counter;
private float dist;
private Vector3 aPos;
private Vector3 bPos;
public Transform origin;
public Transform destination;
public float lineDrawSpeed = 6f;
// Use this for initialization
void Start()
{
lineRenderer = GetComponent<LineRenderer>();
aPos = new Vector3(origin.position.x, origin.position.y, origin.position.z); // Using these to move the lines back
bPos = new Vector3(destination.position.x, destination.position.y, destination.position.z);
lineRenderer.SetPosition(0, aPos);
lineRenderer.SetWidth(3f, 3f);
dist = Vector3.Distance(origin.position, destination.position);
}
// Update is called once per frame
void Update()
{
if (counter < dist)
{
counter += .1f / lineDrawSpeed;
float x = Mathf.Lerp(0, dist, counter);
Vector3 pointA = aPos;
Vector3 pointB = bPos;
Vector3 pointAloneLine = x * Vector3.Normalize(pointB - pointA) + pointA;
lineRenderer.SetPosition(1, pointAloneLine);
}
}

Unless I'm overlooking some logic error in the code you've posted, I think the problem might be with the material.
Generic debugging help for line renderers:
Try setting the color/material of the line renderer:
lineRenderer.sortingOrder = 1;
lineRenderer.material = new Material (Shader.Find ("Sprites/Default"));
lineRenderer.material.color = Color.red;
If that doesn't work, perhaps you need to specify the number of vertexes manually?
mineLaser.SetVertexCount (2);
Finally, if these both don't work, it might just be a logic error; try setting the transforms for the lineRenderer's position to be some predefined value and see if it shows up.
For this specific question:
Ah, so its on a canvas. Assuming you mean the UI canvas, I believe linerenderer is the wrong tool to use in this situation. Check out this question.
One of the answers there suggests to:
just use a panel filled with any color you want and use Height and Width to set the length and the Width of your line

This is impossible in "Screen Space - Overlay" Canvas mode. In that mode UI overlay draws on top of everything in Scene (including LineRenderer, that actually non UI element).
Try to use "Screen Space - Camera" option for your Canvas and "Use World Space" option for you Line Renderer.

I think you must have forgotten to set sorting layer for the line renderer. As this could only be the possible reason if the line is visible in the scene view and not in the game view.

Related

How do i make a stickman's arms reach out to the mouse cursor?

Stickman
I have this stickman here in unity 2D and i want his arms to always reach out to the direction of the mouse. I have no ideas on where i should start and i'm hoping someone here could help me out. Thanks!
Foremost, you need to determine the mouse position. It can be done with the following method:
public Vector3 GetMouseWorldPosition()
{
Vector3 mouseScreenPosition = UnityEngine.Input.mousePosition;
Vector3 mouseWorldPosition = Camera.main.ScreenToWorldPoint(mouseScreenPosition);
return mouseWorldPosition;
}
I use Camera.main here for demonstration purposes. In sake of performance it will be better to cache it as a field in your class.
Now, when you have the target coordinates, you can rotate the hand. Here is an example method:
public void RotateLimb()
{
Vector3 rotationTargetPosition = GetMouseWorldPosition();
Vector3 directionVector = (rotationTargetPosition - _limb.transform.position).normalized;
float angleInRad = Mathf.Atan2(directionVector.y, directionVector.x);
Vector3 targetAngle = _limb.transform.eulerAngles;
targetAngle.z = angleInRad * Mathf.Rad2Deg;
_limb.rotation = Quaternion.Euler(targetAngle);
}
Method RotateLimb() can be called in Update or a coroutine.
All the variables of this method can also be stored as private fields in your class.
_limb must contain Transform of your hand GameObject and you can assign it as SerializeField
[SerializeField] private Transform _limb;
_limb will rotate around its pivot. Therefore, pivot must be in the center of the shoulder. In order to achieve it, you can place all the graphics of your hand as a child of _limb and adjust it accordingly.
This seems like the most straightforward way to do it.

Converting mouse coordinates for ui in world space

Im having problems with position convertions. The way im trying to solve it may be very wrong but thats due to inexperience in that case and im up for any suggestion on how to do it differently.
What im trying to do is a gui with a dot graph envelope that the user can change by draging the dots with the mouse.
This is what i would wan it to look like.
https://imgur.com/FP6f1Cz
First i did the UI like normal in overlay but i couldnt get the line renderer to work so i took the whole ui into world space. This makes the line renderer visible. With the UI in world space ive tried both to put the envelope line renderer in the canvas with the rest of the ui and outside the canvas UI.
Here is the code that renders the lines where the dots are and moves the dots when the mouse drags them :
public class Envelope : MonoBehaviour
{
LineRenderer lineRenderer;
// Start is called before the first frame update
void Start()
{
lineRenderer = GetComponentInChildren<LineRenderer>();
}
// Update is called once per frame
void Update()
{
var points = GetComponentsInChildren<EnvelopePoint>().Select(ep => ep.transform.localPosition).ToArray();
lineRenderer.positionCount = points.Length;
lineRenderer.SetPositions(points);
}
}
public class EnvelopePoint : MonoBehaviour
{
[SerializeField] bool isHeld = false;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (isHeld)
{
// Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector3 mousePos = Input.mousePosition;
transform.position = mousePos;
}
}
private void OnMouseDown()
{
isHeld = true;
}
private void OnMouseUp()
{
isHeld = false;
}
}
The best result is to put the envelope outside of the canvas.
The lines render well to where the points are but im not able to convert the mouse position to correct coordinates for the dots. When i click on a dot to drag it the dot snaps to a position a bit lower and a bit to the left of the mouse. Like this:
https://imgur.com/3KK6VD3
But then i can drag the dots and the lines adjust perfectly.
I guess i have two questions:
How should i get the mouse position conversion correctly?
Is this a strange or over complicated way of doing this? Is there a more reasonable way?
Id love some tip as well on what i should read up on to better understand the different screen types and how to convert between them.
RectTransformUtility.ScreenPointToWorldPointInRectangle: Transform a screen space point to a position in world space that is on the plane of the given RectTransform.
There is also ScreenPointToLocalPointInRectangle but since you are modifying Line Renderer's points (which are in world space), I think ScreenPointToWorldPointInRectangle best suits your needs.

Unity 2D - Keep Player Object in Boundary of it's Parent Panel

In Unity i have a UI Panel which has a player object (an UI Image object).
I moving player object into planel with user inputs (keyboard or touch)
I can't keep player object in it's parent panel,
Please check below image, I want to keep player inside of Red Panel
Here is my Tried Code
public Camera MainCamera; //be sure to assign this in the inspector to your main camera
private Vector2 screenBounds;
private float objectWidth;
private float objectHeight;
private RectTransform pnlBackgroundTransform;
private void Start()
{
pnlBackgroundTransform = GameObject.Find("PnlBackground").GetComponent<RectTransform>();
screenBounds = MainCamera.ScreenToWorldPoint(new Vector3(pnlBackgroundTransform.rect.width , pnlBackgroundTransform.rect.height , MainCamera.transform.position.z));
objectWidth = transform.GetComponent<SpriteRenderer>().bounds.extents.x; //extents = size of width / 2
objectHeight = transform.GetComponent<SpriteRenderer>().bounds.extents.y; //extents = size of height / 2
}
void LateUpdate()
{
Vector3 viewPos = transform.position;
viewPos.x = Mathf.Clamp(viewPos.x, screenBounds.x * -1 + objectWidth, screenBounds.x - objectWidth);
viewPos.y = Mathf.Clamp(viewPos.y, screenBounds.y * -1 + objectHeight, screenBounds.y - objectHeight);
Debug.Log(screenBounds);
Debug.Log(viewPos);
transform.position = viewPos;
}
I'd say it's not very usual having the player implemented as a UI element, and instead you should be implementing it outside the UI/Canvas system.
The UI/Canvas system uses a set of rules of placing and scaling to deal with responsive design. You have at least 4 values (excluding rotation) to place something on the screen: anchor, pivot, position and scale.
For example: if you want to create a square you can either set it's size in absolute pixel values or relative values (to parent). If you're using absolute values, your UI Scale Mode, defined on the Canvas object, should affect the visual results.
This means the UI/Canvas is for elements that should adapt to the screen, such as buttons, dialogs, labels, etc. Taking advantage of device parameters to improve the UX.
Outside the UI/Canvas system, things are directly based on Linear Algebra: you have a 3D vector space (a "World") where everything exists with an absolute size and position. Then, your Camera stretches and twists the whole world to match what your current perspective. That means your object will always have the same size, regardless of screen size.
Now, assuming you have a very specific reason to implement your game into UI, there are a few ways you can do it. I'll assume you're using absolute values. Please note all the units used here are pixels, and the effect should be different for devices with different resolutions and sensible to the UI Scale Mode parameter. Also, please note I've set both anchors min and max to (0,0), the bottom left corner (default is screen center, (0.5,0.5)), in order to avoid negative coordinates.
The following script is attached to the player's UI Image.
public class UIMovementController : MonoBehaviour
{
public float speed = 5.0f;
new private RectTransform transform;
private Rect canvasRect;
private void Start()
{
transform = GetComponent<RectTransform>();
canvasRect = GetComponentInParent<Canvas>().pixelRect;
}
void Update()
{
// Keyboard Input (Arrows)
Vector2 move = new Vector2(0,0);
if (Input.GetKey(KeyCode.UpArrow)) { move.y += speed; }
if (Input.GetKey(KeyCode.DownArrow)) { move.y -= speed; }
if (Input.GetKey(KeyCode.LeftArrow)) { move.x -= speed; }
if (Input.GetKey(KeyCode.RightArrow)) { move.x += speed; }
transform.anchoredPosition += move;
// Position clamping
Vector2 clamped = transform.anchoredPosition;
clamped.x = Mathf.Clamp(clamped.x, transform.rect.width / 2, canvasRect.width - transform.rect.width / 2);
clamped.y = Mathf.Clamp(clamped.y, transform.rect.height / 2, canvasRect.height - transform.rect.height / 2);
transform.anchoredPosition = clamped;
}
}

Player stops move the character direction resets [Unity 2D]

My character is a car and I try to rotate it the direction it move, so far so good I succeeded to do that but once I stop moving the character flips back to the direction it was on the start.
Also how can I make my turns from side to the opposite site smooth ?
Here is my code so far:
[SerializeField] float driveSpeed = 5f;
//state
Rigidbody2D myRigidbody;
// Start is called before the first frame update
void Start()
{
myRigidbody = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
Move();
}
private void Move()
{
//Control of velocity of the car
float HorizontalcontrolThrow = CrossPlatformInputManager.GetAxis("Horizontal"); // Value between -1 to 1
float VerticalcontrolThrow = CrossPlatformInputManager.GetAxis("Vertical"); // Value between -1 to 1
Vector2 playerVelocity = new Vector2(HorizontalcontrolThrow * driveSpeed, VerticalcontrolThrow * driveSpeed);
myRigidbody.velocity =playerVelocity;
**//Direction of the car**
Vector2 direction = new Vector2(HorizontalcontrolThrow, VerticalcontrolThrow);
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
myRigidbody.rotation = angle;
}
I'm not sure about this, but maybe that last line "myRigidbody.rotation = angle" being called every frame is what is making your car reset its rotation.
Maybe change it to "myRigidbody.rotation *= angle" or "myRigidbody.rotation += angle".
It looks like it may be because HorizontalcontrolThrow and VerticalcontrolThrow are going to be reset when you release the controls. If it's resetting to its original orientation, then what's happening is that until you move, those two values are going to be at their default value. You then move and it affects the rotation. But when you release the controls, those values are back to the starting values again, and so is your rotation.
What you therefore need to do is try to separate the HorizontalcontrolThrow and VerticalcontrolThrow from the rest of the code, which should only be activated when at least one of these two variables are not at their default setting (I can't remember what the axis functions return at the moment).
Edit:
An IF statement should suffice (some rough pseudo code):
if (horizontalAxis != default || verticalAxis != default)
{
Rotate/Move
}
I solved the snap rotation using Quaternion at rotation, the issiu I had with it was to convert it from 3d to 2d, through the guide of this clip: youtube.com/watch?v=mKLp-2iseDc and made my adjustments it works just fine !

how to get background to scroll with player height in unity?

I am making an endless jumper. I am trying to get the BG to scroll down based on the players height.
I have seen code that moves the code at a specific speed:
public float speed = .5f;
void Updated(){
Vector2 offset = new Vector2(0, Time.deltatime * speed);
GetComponent<Renderer>().material.mainTextureOffset = offset;
}
I want to move it with the height of the player.
public float PlayerHeight;
So now I need to set the height of the BG. I can't figure out how to do this part.
Transform background;
public float backgroundHeightY;
public GameObject BackGround;
from here I am stuck. I don't want it to move with the camera, but move at a certain rate based on the height of the player. Any help would be awesome.
It sounds like you have a background that has a fixed position relative to the camera, but you want the background to scroll "against" the player as they move up and down, giving a parallax effect?
public Transform player;
public float multiplier = 0.1f; //Tweak this
void Update(){
Vector2 offset = new Vector2(0, player.position.y * multiplier);
GetComponent<Renderer>().material.mainTextureOffset = offset;
}
I have it working well going up, but not down. Here is how it is working going up. I have adjusted the backgroundModifier to fit the timing I need.
//Changes the BG position
changeAmount = (playerHeightY - currentCameraHeight)/backgroundModifier;
Vector3 temp = new Vector3(0, changeAmount, 0);
BackGround.transform.position += temp;
Anyone have an idea on how to get the falling to work. I feel like I am making this harder than it needs to be.
Here is how I finally did this. I actually switched the camera from orthographic to perspective. It took a lot of tweaking to layout, but it ended up working perfectly well. So the code I have above I deleted.