Black traces on screen - unity3d

I am building a simple pizza slicing game in Unity. I have a Sprite with a collider attached as the pizza, and whenever I drag the mouse over the collider, it gets an enter point and an exit point and draws a transparent line between them, pretty much like this:
The problem is, whenever I move the pizza, the line leaves some sort of trace behind it, even if I disable the line renderer or the whole pizza game object. The only solution I have found for this, is to resize the game window, and everything goes back to normal.
Also, if I play my game in maximized mode, the screen fills with black lines, which is very odd. As before, if I resize my game window everything goes back to normal. Here is a screenshot:
Does anyone have an idea on how to solve this problem? Or, at least, go around it by resizing the game window somehow from the script, during play mode? I already tried resizing the camera and changing the resolution, but it does not change anything.
This is how I draw the lines:
void OnTriggerEnter2D (Collider2D other)
{
enterPoint = LineDrawer.instance.mousePos;
enterPoint.z = 0;
points.Add (enterPoint);
}
void OnTriggerExit2D(Collider2D other)
{
exitPoint = LineDrawer.instance.mousePos;
exitPoint.z = 0;
points.Add (exitPoint);
GameObject obj = new GameObject ();
GameObject instance = Instantiate (obj, transform.position, Quaternion.identity) as GameObject;
Destroy (obj);
instance.transform.SetParent (transform);
instance.name = "Cut";
linerenderer = instance.AddComponent<LineRenderer> ();
linerenderer.material = new Material(Shader.Find("Diffuse"));
linerenderer.useWorldSpace = false;
linerenderer.SetWidth (0.15f, 0.15f);
linerenderer.SetVertexCount (2);
linerenderer.SetPosition (0, enterPoint);
linerenderer.SetPosition (1, exitPoint);
}

The problems that I can see here are:
You should not give Quaternion.identity when you create it. You are making it a child. It should have the same rotation with the parent, or else your local positions won't work:
GameObject instance = Instantiate (obj, transform.position, transform.rotation) as GameObject;
You are not using world space for the line. I bet your enterPoint and exitPoint are in world space. Try this:
linerenderer.SetPosition (0, linerenderer.transform.InverseTransformPoint(enterPoint));
linerenderer.SetPosition (1, linerenderer.transform.InverseTransformPoint(exitPoint));
Why are you doing all this in Trigger functions? There is no if, so these functions execute whenever the pizza hits anything.

Related

2D Object Not Detecting When Hit by Raycast

I'm creating a top down 2D game, where the player has to break down trees. I made it so the player casts a ray toward the mouse, and when the ray hits a tree, it should lower the tree's health. I don't get any errors when I run the game or click, but it seems like the tree isn't detecting the hits.
void Update()
{
...
if (Input.GetMouseButtonDown(0))
{
RaycastHit2D hit = Physics2D.Raycast(playerRb.transform.position, mousePosition - playerRb.transform.position, 2.0f);
if (hit.collider != null)
{
if (hit.collider == GameObject.FindWithTag("Tree"))
{
hit.collider.GetComponent<TreeScript>().treeHealth--;
}
}
}
}
Still pretty new to coding and I'm teaching myself, so please make your answer easy to understand to help me learn.
Input.mousePosition is equal to the pixel your mouse is on. This is very different than the location your mouse is pointing at in the scene. To explain further, Input.mousePosition is where the mouse is. Think about it. If the camera was facing up, the mouse positon would be the same, but where they are clicking is different.
Instead of using Input.mousePosition, You should pass this into a function called Ray Camera.ScreenPointToRay();
You just input the mouse position and then use this new ray to do the raycast.
ANOTHER EXTREMELY IMPORTANT THING 1: Do not use Camera.main in Update(), as it uses a GetComponet call, which can cause perormance decreases. Store a reference of it in your script and use that.
Extremely important thing 2: I notice you are using GetComponent to change the tree's health. This is fine, but do not use GetComponent if you don't have to.
Like this:
Camera cam;
void Start()
{
cam = Camera.main; //it is fine to use this in start,
//because it is only being called once.
}
void Update()
{
...
if (Input.GetMouseButtonDown(0))
{
Ray ray = cam.ScreenPointToRay(Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast(ray);
...
}
}
You need to convert your mouse position from screen point to world point with Z value same as the other 2D objects.
Vector3 Worldpos=Camera.main.ScreenToWorldPoint(mousePos);
Also use a Debug.DrawRay to check the Raycast
Debug.DrawRay(ray.origin, ray.direction*10000f,Color.red);
Source

Gently move prefabs to open space before instantiating a new one

i'm trying to instantiate several prefabs in front of the camera using this code:
public GameObject prefab;
private uint instantiatedPrefabs = 0;
public void createObj()
{
if(instantiatedPrefabs < 10)
{
Instantiate(prefab, new Vector3(1, prefab.GetComponent<Renderer>().bounds.size.y/2, 1), Quaternion.identity);
instantiatedPrefabs++;
}
}
It works flawlessly, but if a new prefab appears inside one or several preexisting prefabs, then the preexisting prefabs experience something like an explosion and get flown away of the new one.
How can i detect there are prefabs in the position where i want to put the new prefab and gently move them to the sideways to open enough space?
Easiest would be to have a patter in mind like a grid or something. So you know you're going to spawn 10 game objects so just place them at like new Vector3(1 , instantiatedPrefabs , 1) so they'll just be in a vertical line. You can have a variable for x position.

move object and it's children out of camera in unity2d

I have made a gameobject together with some children gameobject to represent the information to show up when specific circumstances occurred.
I have already ajusted the position of the information gameobject(together with its' children) in the cameraarea. The thing is that I want to move the gameobject(together with its' children) out of the camera, maybe on top or maybe on left. Following is the scratch to demonstrate the position I want to put it:
So that I could move the information gameobject and its' children (Red box) with some movement effect when needed, I have no problem with moving it back but could find an elegant way to move it out of the camera when the game started.
Mostly because I don't know how to calculate the position out of the camera.
Maybe find the upper border of the camera and the size of the gameobject and its children?
I know I could do this by maybe add a marker gameobject to represent the downer border of the information gameobject, and move it until it's not visible, but is there a more elegant way?
Any ideas?
For this one, I would use the following trick: use any method (animation, coroutine, Update method...) to move your item out of screen the way you desire. Then you can use the OnBecameInvisible event which is called when the item does not need to be rendered on any camera anymore. The event will there be used to detect that the parent object moved out of screen, and that you want to stop the current movement. You then just need to define in this event that you want to stop the current moving behavior, and you will be done.
void OnBecameInvisible() {
// Stop moving coroutine, moving in Update or current animation.
}
There are probably more elegant ways of doing it as you said, but I think this method should be enough for what you want to achieve.
It took me time, but I found this way for you, attach this script to your gameObject:
public Renderer rend;
//drag the camera to the script in the inspector
public Camera camera1;
Vector3 bottomleft;
Vector3 topright;
void Start()
{
rend = GetComponent<Renderer>();
//the top-right point of the camera bounds
topright= camera1.ViewportToWorldPoint(new Vector3(0, 0, transform.position.z));
//the bottom-left point of the camera bounds
bottomleft = camera1.ViewportToWorldPoint(new Vector3(1, 1, transform.position.z));
StartCoroutine(MoveUp());
}
IEnumerator MoveUp()
{
//while the position and the height are lower that the Y of top right
while (transform.position.y + rend.bounds.size.y < topright.y)
{
//move the object to the new position (move it up)
transform.position = new Vector3(transform.position.x, transform.position.y + .01f, transform.position.z);
//and wait for 1/100 of a second
yield return new WaitForSecondsRealtime(.001f);
}
}
you can play with the WaitForSecondsRealtime value to change the velocity of moving.

Unity 3D - Cannot set the parent of my collided GameObject

This bug is doing my head in and I can't figure it out!
I have an empty gun, and when I move it near the magazine it has a collide trigger that grabs the magazine, scales it and inserts it into the gun. This bit works fine. However in the code i also set the magazine parent to the gun and set the gravity to false and isKinematic to true - these bits do not happen. Therefore the magazine scales to the gun and then floats off into the distance and when I look in Unity it is not set to be a child of the gun and gravity and kinematic are both unchecked even though I clearly set these below. How is the magazine being scaled and positioned correctly but the parent and rigidbody edits are not being made?
Here is the code:
//THIS CLASS IS A CHILD OF THE GUN
public class GunBody : MonoBehaviour {
void OnTriggerEnter(Collider collider)
{
Debug.LogError("collision with well");
//check if the collision was with the magazine
if (collider.gameObject.name == "Magazine 1")
{
//reload the gun if it was
addClip(collider.gameObject);
}
}
public void addClip(GameObject magazine)
{
magazine.transform.parent = transform.parent; //DOES NOT WORK
magazine.transform.position = transform.parent.position;
magazine.transform.rotation = transform.parent.rotation;
magazine.transform.localRotation = Quaternion.Euler(-89.96101f, 0f, 0f);
magazine.transform.localScale = new Vector3(14f, 20f, 20f);
magazine.transform.localPosition = new Vector3(0f, -0.8215461f, 1.64772f);
magazine.GetComponent<Rigidbody>().useGravity = false; //DOES NOT WORK
magazine.GetComponent<Rigidbody>().isKinematic = true; //DOES NOT WORK
}
Hopefully someone can spot what is going wrong?
Thanks
when you do magazine.transform.parent = transform.parent; you set your script's parent as a parent of magazine. I don't know how your code is organized, but are you sure you want to set magazine as a child of GunBody's object parent? And also maybe try using magazine.transform.SetParent(this.transform).
This scale and positioning problems come from not having (1,1,1) scale of gun. Try to put a gun and a magazine to another empty object.
You can do
magazine.transform.SetParent(transform.parent, false);
So it will be set according to position and orientation of Parent. No need to write First 3 lines of code to set Parent Position and Rotation.

Unity3D OffNavMesh jump issue

I have set up Unity navigation meshes (four planes), navigation agent (sphere) and set up automatic and manual off mesh links. It should now jump between meshes. It does jump between meshes, but it does that in straight lines.
In other words, when agent comes to an edge, instead of actually jumping up (like off mesh link is drawn) it just moves straight in line but a bit faster. I tried moving one plane higher than others, but sphere still was jumping in straight line.
Is it supposed to be like this? Is it possible to set up navigation to jump by some curve? Or should I try to implement that myself?
I came by this question, and had to dig through the Unity sample. I just hope to make it easier for people by extracting the important bits.
To apply your own animation/transition across a navmesh link, you need to tell Unity that you will handle all offmesh link traversal, then add code that regularly checks to see if the agent is on an offmesh link. Finally, when the transition is complete, you need to tell Unity you've moved the agent, and resume normal navmesh behaviour.
The way you handle link logic is up to you. You can just go in a straight line, have a spinning wormhole, whatever. For jump, unity traverses the link using animation progress as the lerp argument, this works pretty nicely. (if you're doing looping or more complex animations, this doesn't work so well)
The important unity bits are:
_navAgent.autoTraverseOffMeshLink = false; //in Start()
_navAgent.currentOffMeshLinkData; //the link data - this contains start and end points, etc
_navAgent.CompleteOffMeshLink(); //Tell unity we have traversed the link (do this when you've moved the transform to the end point)
_navAgent.Resume(); //Resume normal navmesh behaviour
Now a simple jump sample...
using UnityEngine;
[RequireComponent(typeof(NavMeshAgent))]
public class NavMeshAnimator : MonoBehaviour
{
private NavMeshAgent _navAgent;
private bool _traversingLink;
private OffMeshLinkData _currLink;
void Start()
{
// Cache the nav agent and tell unity we will handle link traversal
_navAgent = GetComponent<NavMeshAgent>();
_navAgent.autoTraverseOffMeshLink = false;
}
void Update()
{
//don't do anything if the navagent is disabled
if (!_navAgent.enabled) return;
if (_navAgent.isOnOffMeshLink)
{
if (!_traversingLink)
{
//This is done only once. The animation's progress will determine link traversal.
animation.CrossFade("Jump", 0.1f, PlayMode.StopAll);
//cache current link
_currLink = _navAgent.currentOffMeshLinkData;
//start traversing
_traversingLink = true;
}
//lerp from link start to link end in time to animation
var tlerp = animation["Jump"].normalizedTime;
//straight line from startlink to endlink
var newPos = Vector3.Lerp(_currLink.startPos, _currLink.endPos, tlerp);
//add the 'hop'
newPos.y += 2f * Mathf.Sin(Mathf.PI * tlerp);
//Update transform position
transform.position = newPos;
// when the animation is stopped, we've reached the other side. Don't use looping animations with this control setup
if (!animation.isPlaying)
{
//make sure the player is right on the end link
transform.position = _currLink.endPos;
//internal logic reset
_traversingLink = false;
//Tell unity we have traversed the link
_navAgent.CompleteOffMeshLink();
//Resume normal navmesh behaviour
_navAgent.Resume();
}
}
else
{
//...update walk/idle animations appropriately ...etc
Its recommended to solve your problems via animation. Just create a Jump animation for your object, and play it at the correct time.
The position is relative, so if you increase the Y-position in your animation it will look like the object is jumping.
This is also how the Unity sample is working, with the soldiers running around.
Not sure what version of unity you are using but you could also try this, I know it works just fine in 4:
string linkType = GetComponent<NavMeshAgent>().currentOffMeshLinkData.linkType.ToString();
if(linkType == "LinkTypeJumpAcross"){
Debug.Log ("Yeah im in the jump already ;)");
}
also just some extra bumf for you, its best to use a proxy and follow the a navAgent game object:
Something like:
AIMan = this.transform.position;
AI_Proxy.transform.position = AIMan;
And also be sure to use:
AI_Proxy.animation["ProxyJump"].blendMode = AnimationBlendMode.Additive;
If you are using the in built unity animation!
K, that's my good deed for this week.
Fix position in update()
if (agent.isOnOffMeshLink)
{
transform.position = new Vector3(transform.position.x, 0f, transform.position.z);
}