How to shoot particle like projectile? - unity3d

I made a tank that shoot sphere balls on mouse click.
my C# script:
GameObject prefab;
// Use this for initialization
void Start () {
prefab = Resources.Load("projectile") as GameObject;
}
// Update is called once per frame
void Update() {
if (Input.GetMouseButtonDown(0))
{
GameObject projectile = Instantiate(prefab) as GameObject;
projectile.transform.position = transform.position + Camera.main.transform.forward * 2;
Rigidbody rb = projectile.GetComponent<Rigidbody>();
rb.velocity = Camera.main.transform.forward * 40;
}
}
in this script im shooting a mesh named projectile. But I want to shoot a particle ball and not a mesh. I already tried to change the particle to Orbparticle on script but no object was spawned. What im doing wrong?

No object was spawned because you probably don't have a resource called Orbparticle. Check if you have any errors when you run your script. If Resources.Load doesn't find the object you want by the path you gave it, it will give null, which probably why no object is being spawned.
If you want to shoot a particle instead of a mesh then what you need to do is set prefab to a GameObject you prepared ahead of time that has the ParticleSystem you want. I'd suggest against using Resources.Load for this.
1. Using Resources.Load.
Change your code to this so that it will alert you if it doesn't find the resource:
GameObject prefab;
// Use this for initialization
void Start () {
string name = "OrbParticle";
prefab = Resources.Load<GameObject>(name);
if (prefab == null) {
Debug.Error("Resource with name " + name + " could not be found!");
}
}
// Update is called once per frame
void Update() {
if (Input.GetMouseButtonDown(0))
{
GameObject projectile = Instantiate(prefab) as GameObject;
projectile.transform.position = transform.position + Camera.main.transform.forward * 2;
Rigidbody rb = projectile.GetComponent<Rigidbody>();
rb.velocity = Camera.main.transform.forward * 40;
}
}
Now in order for this to work you need a prefab called "OrbParticle" or whatever string you set the variable name to. Resources.Load looks for items in paths such as Assets/Resources. So you MUST have your "OrbParticle" prefab located in that Resources folder. Unless you have a specific reason for using Resources.Load, I strongly suggest you go with solution 2.
2. Ditching Resources.Load and using the Prefab directly.
Change your code to this:
public GameObject prefab;
// Update is called once per frame
void Update() {
if (Input.GetMouseButtonDown(0))
{
GameObject projectile = Instantiate(prefab) as GameObject;
projectile.transform.position = transform.position + Camera.main.transform.forward * 2;
Rigidbody rb = projectile.GetComponent<Rigidbody>();
rb.velocity = Camera.main.transform.forward * 40;
}
}
Then do this:
Create a new empty GameObject.
Attach a ParticleSystem to the GameObject.
Make a new prefab asset.
Drag and drop the newly created GameObject into a Prefab asset.
Drag and drop the the prefab into prefab field in your Monobehaviour (the object doing the shooting. It will have a prefab field in the Inspector. That's why we set prefab to be a public field).
If you continue having problems, look in Unity's Hierarchy to see if no object is being created at all. It might be the case that it is instantiating a GameObject but the GameObject is invisible for some reason or not instantiating in the location you expect.

Related

How to add a spawner on a side of moving camera in unity2D

I'm creating a 2D racing game in Unity2D and unsure how to approach on coding my spawner for objects e.g. power-up, rewards and obstacles ahead on the right side of my moving camera. The camera follows my vehicle and moves from left to right. Currently objects spawn in the game, but only spawn on a point and continue to spawn in the same point when the camera has scrolled way past. Apologies, if the answer was simple.
Here are the scripts I used:
coin.cs is attached to my coin prefab
public class coin : MonoBehaviour
{
public Camera mainCamera;
Rigidbody2D rb;
// Start is called before the first frame update
void Start()
{
mainCamera = GameObject.FindObjectOfType<Camera>();
rb = this.gameObject.GetComponent<Rigidbody2D>();
transform.position = new Vector2(mainCamera.pixelWidth / 32, getRandomHeight());
}
float getRandomHeight(){
return Random.Range(-(mainCamera.pixelHeight / 2) / 100, (mainCamera.pixelHeight / 2) / 100);
}
private void OnTriggerEnter(Collider coll){
if (coll.gameObject.tag == "Player"){
Destroy(this.gameObject);
}
}
// Update is called once per frame
void Update()
{}
}
and coinSpawner.cs is attached to a gameObject in the scene
public class coinSpawner : MonoBehaviour
{
float LastSpawnTime = -500f;
float NextSpawnTime = 3;
public Object CoinPrefab; // declare coinPrefab
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Time.time - LastSpawnTime > NextSpawnTime)
{
NextSpawnTime = Random.Range(3, 10);
LastSpawnTime = Time.time;
Instantiate(CoinPrefab);
}
}
Instantiate(CoinPrefab);
spawns this object without any information of position or parent object. This it will always be spawned at Scene root and 0,0,0.
Then this line
transform.position = new Vector2(mainCamera.pixelWidth / 32, getRandomHeight());
in coin always places it to the absolute position depending on your pixelWidth which doesn't change over time.
You are saying the Camera is moving so you should rather take it's transform.position into account.
You have basically two(three) ways to go here:
You can make the spawner GameObject a child of your Camera - so it is automatically moved along with it - and move it to the right to have the desired offset. Then simply spawn new objects at this GameObjects position. Then you can do it in coinSpawner:
Instantiate(CoinPrefab, transform.position, Quaternion.Identity);
Or get the Camera reference and use it's position + the desired offset either also only in coinSpawner like
// reference this already via the Inspector if possible
[SerializeField] Camera _camera;
// Otherwise get the reference on runtime
void Awake()
{
if(!_camera)_camera = Camera.main;
}
float getRandomHeight => Random.Range(-(_camera.pixelHeight / 2) / 100, (_camera.pixelHeight / 2) / 100;
and then do something like
Instantiate(CoinPrefab, new Vector2(_camera.transform.position.x + mainCamera.pixelWidth / 32, getRandomHeight()), Quaternion.Identity);
This would actually be more efficient since the entire coin script would be reduced to only the OnTriggerEnter part and not every coin would use FindObjectOfType and GetComponent when spawned.
Basically the same as above but sticking to your code structure simply do
transform.position = new Vector2(mainCamera.transform.position.x + mainCamera.pixelWidth / 32, getRandomHeight());
I wouldn't do it this way though due to efficiency as said.

How to create a projectile Script in Unity

so recently my friends and I are trying to make a game for fun. Currently, I hit a wall and not sure how to do this. I am trying to create a simple base script where I have the character move and attack with right click. If it hits the ground, it will move there and and if in range of a target, it will send a projectile. So the game is creating the projectile but its not actually moving. Can anyone tell me what I should probably do. At first, I thought to just make it all one script but now I am thinking it be best to make another script for the projectile.
void Update()
{
if (Input.GetMouseButtonDown(1))
{
RaycastHit hit;
if(Physics.Raycast (Camera.main.ScreenPointToRay(Input.mousePosition), out hit) && hit.transform.tag == "Minion")
{
if(Vector3.Distance(this.transform.position, hit.point) <= atkRange)
{
GameObject proj = Instantiate(bullet) as GameObject;
proj.transform.position = Vector3.MoveTowards(this.transform.position, target, atkSpd);
}
}
else if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, speed))
{
agent.destination = hit.point;
}
}
}
So this is what I originally had. I am pretty sure I did something wrong here. Also I am not sure if I should have another script for the projectile itself or if it is not necessary. Thank you for any help or tips on what to do.
For starters, I'd advize using a Rigidbody component and letting physics handle movement but if you'd like to use Vector3.MoveTowards, it'll be a bit of work:
Vector3.MoveTowards is something that needs to be called every frame. I'm guessing bullet is your prefab so you'll want to make a new script for the movement and place it on that prefab:
public class MoveToTarget : MonoBehaviour
{
private float _speed;
private Vector3 _target;
public void StartMovingTowards(Vector3 target, float speed)
{
_target = target;
_speed = speed;
}
public void FixedUpdate()
{
// Speed will be 0 before StartMovingTowards is called so this will do nothing
transform.position = Vector3.MoveTowards(transform.postion, _target, _speed);
}
}
After you've attached this to your prefab, make sure you grab a reference and get it started when you instantiate a copy of your prefab:
GameObject proj = Instantiate(bullet) as GameObject;
var movement = proj.GetComponent<MoveToTarget>();
movement.StartMovingTowards(target, atkSpd);
If you instead go the physics route, add a Rigidbody component to your bullet prefab, and get a reference to that instead of making the MoveToTarget script:
GameObject proj = Instantiate(bullet) as GameObject;
var body = proj.GetComponent<Rigidbody>();
Then you can just apply a force and let physics take over:
body.AddForce(target - transform.position, ForceMode.Impulse);
Don't set the position like you currently are
proj.transform.position = Vector3.MoveTowards(this.transform.position, target, atkSpd);
Instead, add either a characterController or a rigidbody and use rb.addVelocity.

Unity2D: play instantiated prefab's animation when prefab is being dragged

I have a prefab that is instantiated when the user buys the item from my In-game store, how ever many is instantiated, the all of prefab has a start position of a certain position. The prefab can be dragged around the scene using this TouchScript package I found online! My issue: I want to play the prefab's animation every time the user is dragging the prefab around the screen, I attempted this by creating a RaycastHit2D function that would allow me to detect if the user has clicked on the prefab's collider, script below:
if (Input.GetMouseButtonDown (0)) {
Vector2 worldPoint = Camera.main.ScreenToWorldPoint (Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast (worldPoint, Vector2.zero);
if (hit.collider != null) {
if (this.gameObject.name == "Item5 (1)(Clone)" +item5Increase.i) {
monkeyAnim.SetBool ("draging", true);
Debug.Log (hit.collider.name);
}
} else {
monkeyAnim.SetBool ("draging", false);
}
}
However if I were to buy more than one prefab, all instantiated prefabs will play it's animation when I start to drag only one of the instantiated prefabs, hope I'm making sense. Can some one help me? Thank you!
I faced a similar issue with platforms in my 2D game. The solution I would suggest is to create a GameObject that acts as the current item you wish to animate, and a LayerMask that acts as a filter for which objects your raycast can hit. You can use this LayerMask in conjunction with the Physics2D.Raycast API, which has an overload method that takes a LayerMask as a parameter.
Start by creating a new layer, which can be done by going to the top right of an object in your scene and accessing the "Layer" box. Once you've created a new layer (I called mine "item"), make sure your prefab's layer is assigned correctly.
Then, create an empty object in your scene, and attach this script to it. On that object you will see a dropdown menu that asks which layers your raycast should hit. Assign it the "item" layer; this ensures that your raycast can only hit objects in that layer, so clicking on anything else in your game will produce no effect.
using UnityEngine;
public class ItemAnimation : MonoBehaviour
{
private GameObject itemToAnimate;
private Animator itemAnim;
[SerializeField]
private LayerMask itemMask;
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
CheckItemAnimations();
}
else if (Input.GetMouseButtonUp(0) && itemToAnimate != null) //reset the GameObject once the user is no longer holding down the mouse
{
itemAnim.SetBool("draging", false);
itemToAnimate = null;
}
}
private void CheckItemAnimations()
{
Vector2 worldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast(worldPoint, Vector2.zero, 1, itemMask);
if (hit) //if the raycast hit an object in the "item" layer
{
itemToAnimate = hit.collider.gameObject;
itemAnim = itemToAnimate.GetComponent<Animator>();
itemAnim.SetBool("draging", true);
Debug.Log(itemToAnimate.name);
}
else //the raycast didn't make contact with an item
{
return;
}
}
}

How do I make my Unity3d camera rotate around his following object?

I'm making a game but I do not now how to let my camera rotate with the object he's following. (I did the follow part) Can somebody help me please. I'm using C#.
Please, can you describe what you actually want to do? What does "let my camera rotate with the object" mean?
If you want your camera to exactly follow the gameobject's rotation in a first person camera, you could achieve this by putting your camera as the gameobject's child.
You could also do this using the following code:
[SerializeField]
private Transform obj; //reference the gameobject's transform
void Update()
{
transform.rotation = obj.rotation;
}
You should use the transform.RotateAround to move the camera. This should be done inside the update method in your camera.
For example:
var target:transform;
function Update(){
//...
transform.RotateAround (target.position, Vector3.up, speed * Time.deltaTime);
}
For more information on the rotation method, see the docs.
If you want simple 3rd person camera, you can place camera as a child of your target object - the camera will "stick to it.
If you want to do this in code (for some reasons), something like this should work (attach script to GameObject with Camera component):
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
public Transform target; // Object to fallow. Select in Inspector
public Vector3 offset = new Vector3(0, 0, -10); // Offset to target
private GameObject container; // Container for our camera
void Start()
{
container = new GameObject("Camera Container"); // Create container (empty GameObject) for camera to avoid unnecessary calculations. It will follow the target object
transform.parent = container.transform; // Make this object child of container
}
//Update your camera follow script in LateUpade(), to be sure that 'target' movement is done
void LateUpdate()
{
//Check if target is selected
if (target == null)
return;
container.transform.position = target.position; // Set container position same as target
container.transform.rotation = target.rotation; // Set container rotation same as target
transform.localPosition = offset; // Move camera by offset inside the container
transform.LookAt(target); // Optionaly, force camera look at target object on any offset
}
}

Unity 3D: Instantiating a Prefab OnTriggerEnter

Firstly, this is the script I'm using:
var object: GameObject;
private var obj: GameObject;
function OnTriggerEnter(other: Collider)
{
if (other.tag == "Player"){
obj = Instantiate(object, Vector3(0, 0, 0), transform.rotation);
}
}
Now, with this script, when I enter the Trigger, the Prefab is being instantiated in front of my initial Prefab, just like I wanted it...but when I move to my instantiated Prefab, when I enter the Trigger, the prefab is not being cloned in front but at the same position like the last one.
My game is an endless runner, so I need the spawned prefab to always be one tile further of my last prefab. How can I do this?!
Here's a sketch of the situation, if I'm not being quite clear with you guys
var spawnDistInFrontOfPlayer : float = 2f;
//change this to your axis direction (direction the character will run)
var spawnAxis : Vector3 = Vector3.right;
obj = Instantiate(object, other.transform.position + (spawnAxis * spawnDistInFrontOfPlayer), transform.rotation);
The code you posted instantiates the prefab always at position (0,0,0). You can simply substitute that vector with the actual world space position where you want to spawn the prefab. For example, in front of the player of a few units:
spawnDistInFrontOfPlayer = 2f;
obj = Instantiate(object, other.transform.position + other.transform.forward * spawnDistInFrontOfPlayer, transform.rotation);