I have had this issue for a while and I can not find a solution to fix it. I manage to shoot bullets with trails. To do this, I create a bullet prefab and add a trail renderer to it. I shoot the bullet in another soldier game object by following steps:
Load the bullet prefab:
private void Awake()
{
bulletPrefab = Resources.Load<GameObject>("Enemy/Bullet");
Instantiate bullets from bullet prefab:
private void shoot(){
bullet = Instantiate(bulletPrefab);
bullet.transform.position = this.transform.position;
...
}
Then I update the bullet position according to the calculated angle and bullet speed. The problem is that when I shoot a bullet, the bullet will cast two trails, one trail going toward to the target which I set in the script and the other point to the bullet prefab I load in the Awake function. It seems that the bullet prefab loaded from resource folder does not show in the scene. However it affects the bullets which instantiated from it, making them point a trail to it.
How can I fix this issue?
I have resolved this issue by myself. The cause of this issue is actually pretty simple. I should choose Instantiate(Object original, Vector3 position, Quaternion rotation) rather than Instantiate(Object original).
The first version of instantiate creates the bullet in the given position; relocating the prefab after using the second version will render the unwanted trail.
You can also use the TrailRenderer.emitting option.
just set the emitting to false in by default and right before firing change it to true using myTrail.emitting = true;
Related
I have a parent object with a rigidbody (gravity disabled). With a script I am adding simple cubes with box colliders as children to this parent.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
public GameObject prefab;
void Update()
{
if(Input.GetMouseButtonDown(0))
{
GameObject go = Instantiate(prefab, transform);
go.transform.localPosition = new Vector3(10f, 10f, 10f);
}
}
}
This works fine, but a slight movement of the parent object is visible everytime a cube is instantiated and parented. So eventually after adding quite a few cubes the parent moves even whole units from its original position, although the velocity is always Vector3.zero.
How does this movement happen and how do I prevent it?
So, it appears that the small movement of the rigidbody parent comes from a change in the centre of mass. By moving or instantiating objects as childs this value has been changed as it states in https://docs.unity3d.com/ScriptReference/Rigidbody-centerOfMass.html:
If you don't set the center of mass from a script it will be
calculated automatically from all colliders attached to the rigidbody.
After a custom center of mass set, it will no longer be recomputed
automatically on modifications such as adding or removing colliders,
translating them, scaling etc. To revert back to the automatically
computed center of mass, use Rigidbody.ResetCenterOfMass.
Finally, as solution I just set the local center of mass to a fixed value.
rig.centerOfMass = Vector3.zero;
I am quite happy with this solution, because this also changes the center of rotation. Still I am not quite sure why it adds a movement on a change in the center of mass, because I don't see why that would be realistic behaviour.
Also there is a difference between rigidbody.position and transform.position. By using solutions such as commented under the question:
Unparent, move child, parent again
Disable child, move child, enable child again
Disable the child's collider, move child, enable it again
...it is possible to keep the transform.position the same, but rigidbody.position will still change. This difference between both values persists as long as the rigidbody is asleep. Waking it up e.g. by calling Rigidbody.Wakeup() will sync both values again. Due to a difference in both values even things like a raycast can fail, although the ray might be hitting the spot where the meshes are actually drawn and just the physics engine thinks they are somewhere else. Also waking up again looks ugly because the mesh snaps back into place were it should be to match the rigidbody.
I want to spawn several circles on the screen as game objects that float around randomly. To do this I have a prefab that I am instantiating x number of times in a script attached to a main game object. Then I have a 2nd script attached to the prefab to control the random movement. I added a Particle System to the prefab, so that each spawned clone has particles emitting from its edges. I want to know if one object's particles collide with anything, be it another cloned object, a wall, etc. But my OnParticleCollision (in the movement script attached to the prefab) is not logging anything to the console, it seems to not detect particle collisions at all. Maybe I'm not understanding the bigger concept and instantiating multiple instances of the same prefab with a particle system is not the best approach? Or am I making a more obvious minor mistake?
Things I have tried based on other questions:
Send collision messages IS checked
I do not have any colliders marked as triggers
I verified the visual bounds look correct in Scene View
Collision between cloned game objects themselves work fine, it's only the Particle Collisions not working.
My script attached to the prefab:
public class BubbleMove : MonoBehaviour
{
public Rigidbody2D rb;
void Start()
{
rb.velocity = new Vector2(min, max);
ParticleSystem ps = GetComponent<ParticleSystem>();
ps.transform.position = new Vector3(transform.position.x, transform.position.y, 0);
ps.Play();
}
// Update is called once per frame
void Update()
{
}
void OnParticleCollision(GameObject col){
Debug.Log("Collision Particle: " + col);
}
}
Images of my prefab inspector settings for Rigidbody2D, Circle Collider, and Particle System:
Hi I see the rigidbody is not defined in the inspector for the BubbleMove script.
I'm new to Unity and after watching and reading some tutorials I'm now trying to make a simple 2D platformer kind of game. In the said game both enemies and player can jump to different platforms and traverse it like the old SnowBros game.
The problem I'm facing is related to programming the enemy movement. In my game there would be several types of enemies but generally for now there are two types, one that can jump from the platform and one that only walks upto the length of the platform, wait for 1 second then flip and walk backwards; meaning they don't get off the platform. Now this is an issue I'm having trouble with. I can't seem to find a way to calculate the length of the underlying current platform. I thought of using the collider.bound.min.x and max.x to come around the problem but the issue is I can't seem to find a simple way to reach the current platform's collider without fetching the script and then going through it.
Since, there would be many platforms of many different sizes and each platform is made up of a prefab of other platforms, it just doesn't seem like a workable solution to use the platform script and then traverse through it.
You can use Physics2D.Raycast to "sense" for collisions on a Ray. Imagine the enemy putting their toe one step forward, feeling if there is still solid ground, and then deciding whether to stop.
void Update()
{
Vector2 newPosition = transform.position + velocity * Time.deltaTime;
Vector2 downwardDirection = Vector2.down; // you may have to replace this with your downward direction if you have a different one
RaycastHit2D hit = Physics2D.Raycast(newPosition, downwardDirection);
if (hit.collider != null)
{
// solid ground detected
transform.position = newPosition;
}
else
{
// no ground detected. Do something else...
}
}
You can and should define the Layers your Raycast is supposed to hit, so it can ignore the enemy itself and avoid self-collision.
Well, I hope that you have prefabs of platform and in those prefabs put colliders at start and at end. You can specify layers and tags so that only enemy can detect those colliders and then you can detect tags on collision from enemy script and make your operation.
First create layers by opening Edit -> Project Settings -> Tags and Layers. Create two Layers
Create layers for enemy and enemyColliders and Goto Edit -> Project Settings -> Physics2D. Set collision matrix as EnemyCollider will collider with enemy only.
And your prefab will be looks like,
I hope this would help you.
So im creating a simple game and one component of the game is a greendot following the outside of the level. I got this working using a raycast in the middle which rotates and gives the position of collision the the gameobject.
game overview
The problem is that the speed is inconsistant at the moment since the distance between two collisions can be further distance if i have a slope. I also have the feeling that there should be a easier way to get the same result. What are your thoughts?
public class FollowPath : MonoBehaviour {
Vector3 collisionPos;
public GameObject greenDot;
void Update ()
{
RaycastHit2D hit = Physics2D.Raycast(transform.position, transform.up);
transform.Rotate(0.0f, 0.0f, 3);
if (hit.collider != null)
{
collisionPos = hit.point;
}
greenDot.transform.position = collisionPos;
}
}
I'm not sure if you will like this answer, as it suggests a complete departure from the way you were trying to do it.
A simple way to do this, would be to give your moving dot GameObject a Rigidbody2D component, AND a CircleCollider component.
Then, make your walls, and add to each an EdgeCollider component.
You'll probably also want to add a PhysicsMaterial2d to each GameObject with a Collider and set the friction and bounciness values for each.
Once this is setup, you can apply an initial force to the rigid body ball to get it moving, and it will bounce off the walls just like a ball does, using the Unity physics engine. No code would be needed in you update functions.
I am trying to build a 2D space shooter game where the player will remain constant at the bottom of the screen and will move left and right. When the player fires a bullet(projectile), the bullet is going up just fine, but it is coming back again. Also if two bullets collide, they react to the collision.
I have two questions here:
How can I ensure that the bullet does not come back? (One way is to destroy it after a few seconds, but not sure if this is the right way)
How do I avoid collision between the bullets.
Here is my code snippet:
void Update () {
if (Input.GetButtonDown("Fire1"))
{
Rigidbody2D clone = (Rigidbody2D)Instantiate(bullet, transform.position + transform.up, transform.rotation);
clone.velocity = transform.TransformDirection(Vector3.up * 20);
}
}
I am very new to Unity and somehow wrote this code by looking into Unity Forums.Any help will be very much appreciated.
Thanks
More details:
I have created the bullet and added Rigidbody2D and a BoxCollider2D for this object. Made the bullet object a prefab and I dragged it under the Player object. Now bullet is a child of the Player object. Attached the script above to the Player object.
To answer your immediate questions:
1) I am not too sure about how you have the scene setup or about using the Unity 2D tools but usually if your bullets are coming back down then I would assume that you still have gravity applied to the rigidbody -- so make sure that you have that unchecked.
2) With Unity3D for objects to interact with each other they need rigidbodies attached. This is vital, say, if you want your lasers to destroy Monster #1. However, you only need one rigidbody attached to an object to have a desired effect. I would suggest removing the rigidbody from your laser and attach rigidbodies to objects ( Monster #1 ) that you want to be affected by the laser fire. ( That should work, if not there are other options -- one using layers and ignoring particular objects on those layers ).
Tips:
Here are some extra things. When you are creating objects and they fly off screen over time they will build up. Imagine you are in a large battle and you instantiated hundreds of lasers -- it will eventually be an issue for performance. So always consider Destroying objects after a certain amount of time.
Also, after looking at your code, I can't tell whether the velocity of the object is based upon its current position and nothing is being added. What I think is happening is when you instantiate an object it may be moving up, but because there is no incrementer, the object ( as it gets higher ) slows until it is at a rate which it is falling. For example this
clone.velocity = transform.TransformDirection(Vector3.up * 20);
should probably do this:
clone.velocity += transform.TransformDirection(Vector3.up * 20);
Heres http://docs.unity3d.com/Documentation/ScriptReference/Vector3-up.html, to read up on velocity. The problem is is that you need to continuously apply a constant forward motion so things in motion will tend to stay in motion. If not gravity will pull it down.
Also, heres a bit of code that I've used in the past that's created a pretty cool shooting laser effect thing:
public class Laser : MonoBehaviour {
public int fireRate = 70;
void Start(){
InvokeRepeating("FireLaser", 0.01f, 0.009f);
Destroy( gameObject, 2.0f );
}
void FireLaser(){
transform.Translate( Vector3.up * fireRate * Time.deltaTime );
}
}
edit: it's 3 a.m. and I hate proofreading.