Unity3D: Trail Renderer for no-moving object - unity3d

In my game, my player (a ball) doesn't move in the x-axis. The ball just can jump (y-axis).
The level is always translating in the x-axis and give to the player the sensation the ball is moving.
My question is : Is it possible to add a trail renderer (or something like this) to my ball ? To enforce the sensation of moving of the ball ?
As the image .. :
(source: barouch.fr)
Thank you!

Yes you can, and I've proven that it is possible.
As you can see in the image, I nested 5 spheres recursively, each with Z + 1 of its parent.
You're going to need rigidbody for each of them because we're going to AddForce to them.
And here's the important part, the scripts.
I have 3 scripts, named HeadScript, BodyScript, TailScript (kinda like a snake game, so I name them like that)
HeadScript:
void Update () {
if(Input.GetKeyDown(KeyCode.Space)){
rigidbody.AddForce(new Vector3(0, 6, 0), ForceMode.Impulse);
GameObject child = transform.FindChild("Sphere").gameObject;
BodyScript childScript = child.GetComponent<BodyScript>();
childScript.ChildJump();
}
}
HeadScript is only attached to the head (the rightmost sphere), it needs to detect keydown (for jumping), then we add force to itself (only upwards) so it looks like it's jumping. Afterwards, get the child object, (the ball on its left) and call the function ChildJump which is inside BodyScript.
BodyScript:
public void ChildJump(){
Invoke ("Jump", 0.1f);
}
void Jump(){
rigidbody.AddForce(new Vector3(0, 6, 0), ForceMode.Impulse);
GameObject child = transform.FindChild("Sphere").gameObject;
if(child.GetComponent<BodyScript>() == null){
TailScript childScript = child.GetComponent<TailScript>();
childScript.ChildJump();
}
else {
BodyScript childScript = child.GetComponent<BodyScript>();
childScript.ChildJump();
}
}
BodyScript is attached to every sphere except the first and the last. Parent objects call the function ChildJump which contains only 1 function, Invoke.
Invoke is used to call a function after a certain amount of delay. In this code the delay is 0.1s.
The Jump itself will call its child's (the ball on its left) ChildJump function. Now you see why it is kind of recursive.
We added the if condition so we won't get any errors when we get BodyScript component from the last sphere, which isn't there. The last script has only TailScript.
TailScript:
public void ChildJump(){
Invoke ("Jump", 0.1f);
}
void Jump(){
rigidbody.AddForce(new Vector3(0, 6, 0), ForceMode.Impulse);
}
The final script, TailScript only contains AddForce to itself, because it has no child.
Every sphere (except the head) will jump after 0.1s delay from its parent, becoming what you call it, trail renderer.
Now what's left is just to add alpha material for each of them so they become more transparent, and voila! Job's done!

Related

Unity2D - transform.position is not equal to the real world position

Okay, the title may be confusing cause I don't how to know put it.
My case: I have a 2d sprite with 4 child objects, each one place around the sprite as a perimeter. So it looks like this:
Spawner2 has a script with the following method, which is called at the start of the game. Inside the script, I instantiated a new prefab:
public void GenerateBox(int count)
{
...
GameObject spawnedRoom = Instantiate(possibleRooms[chosen], transform.position, Quaterion.identity);
}
But this instantiates the object at Spawner1's location.
So I tried to debug. I pulled Spawner2 out of its parent and see the location (which is X: 1.0062, Y: -0.0038). I put it back inside the 2d sprite and when I debug.log it's position, it gives me X: 0, Y: 1, Z: -9.8.
Is it because of my prefab? What is the problem and how can I fix it?
Use this overloaded method instead:
Instantiate(Object original, Vector3 position, Quaternion rotation, Transform parent);
and pass the Spawner2 parent transform as the last parameter. Now new object should be positioned in the same place as the Spawner2. In the end your function should look like this:
public void GenerateBox(int count)
{
...
GameObject spawnedRoom = Instantiate(possibleRooms[chosen], transform.position, Quaterion.identity, transform.parent);
}
EDIT: I started a new project and did the exact same thing except now, the prefab position is set to 0 on all axis. Everything works fine now. I'm guessing this happens because of the prefab's position. For example, you instantiate the prefab in the script at (0, 0, 0) world position and the prefab position is (2, 1, 0), then the prefab will spawn at (2, 1, 0) world position. It's position + prefab 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.

Black traces on screen

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.

Collision not detected by OnTriggerEnter

So I'm trying to make a game about soccer. In this program, I'd created 2 objects called (in Hierarchy): Ball and goal_line_1. In this code, I'm trying to check if the ball collides with the goal line or not, and if it does collide, I will return (Lerp) the ball to the point in the middle (0,0.3,0). But somehow when I drag the ball to the position that the ball collides with the goal line and then press play, the ball just stay there and don't return to the middle point.
public var smooth : float;
private var newPosition : Vector3;
function Awake ()
{
newPosition = transform.position;
}
function OnTriggerEnter (ball : Collider)
{
var positionA : Vector3 = new Vector3(0, 0.3, 0);
newPosition = positionA;
ball.transform.position = Vector3.Lerp(ball.transform.position, newPosition, smooth * Time.deltaTime);
}
That is because you used OnTriggerEnter() function. This function is called when a collider enters a collision with another collider. What you do by dragging the ball into the line and then pressing play is actually skipping the 'Trigger Enter' event. There are three main events when it comes to collisions: TriggerEnter, TriggerStay and TriggerExit.
Although I'm not sure, if you change your function to OnTriggerStay(), you might get your function work. However for a safer testing method, I suggest you add a script to the ball so you can manually move it with your keyboard and see if the OnTriggerEnter() function works because by doing that, you will be simulating a more realistic situation (ball being kicked/moving towards the line rather than "suddenly existing" on the line).
If you are using 2D, you need to change your OnTriggerEnter function to OnTriggerEnter2D.

Can I loop a lot of falling objects in unity?

I make 7 cubes and I want to auto drop when the game starts. So I use Gravity to make objects fall. When the game start all cubes are dropped automatically but I want to make it happen again and again. I do not have any idea how to make it. So if you know, please tell me how to make it.
You can do it easily by attaching a script to falling objects to re-position them after going out of focus of the camera or reaching a specific location on the 3D space.
Some simple scripts like this would do,
//Change this to suit your needs
void Update()
{
if (renderer.IsVisibleFrom(Camera.main))
{
Debug.Log("Still Visible");
}
else
{
Debug.Log("Not visible");
transform.position = new Vector3(x, y, z);
}
}
This will not dynamically spawn object nor destroy it would rather reuse existing.
Make your cube into a prefab. Then create a GameObject somewhere in your scene and attach a script to it that spawns the cubes every x seconds.
public Transform MyPrefab;
private float timer = 0f;
void Update() {
timer += Time.deltaTime;
// Spawn a new block every second
if (timer > 1f) {
Instantiate(MyPrefab);
timer -= 1f;
}
}
In the inspector, drag your prefab to the MyPrefab property of your spawning object so it knows what to instantiate.
You should probably attach a script to your prefab cubes that calls Destroy() on them once they fall completely off screen.