Unity Prefab spawn incorrect rotation - unity3d

I have the following simple prefab:
When I add this to my scene, it looks like this:
Very neat!
Then I have the following script on my Character:
public class MageController : MonoBehaviour {
public GameObject Spell;
public float SpellSpeed;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown(KeyCode.H)) {
GameObject newSpell = Instantiate(Spell);
newSpell.transform.position = transform.position;
newSpell.transform.rotation = Quaternion.LookRotation(transform.forward, transform.up);
Rigidbody rb = newSpell.GetComponent<Rigidbody>();
rb.AddForce(newSpell.transform.forward * SpellSpeed);
}
}
}
The goal is of course to make sure that the fireball is spawned correctly (with the tail behind it)
This works when I stand at 0.0.0; it looks like this:
However, if I turn around it looks like this:
As you can see, the rotation of the fireball is not correct (in the above incorrect image it is flying away from me, however, the tail is in front).
What am I doing wrong? How can I make sure that the tail is always correctly placed?
Update after following the guidance of PlantProgrammer
it still turns incorrectly :(
Look at the image below!

You want to use the forward direction of the player and not it's rotation, when instantiating the fireball. (Remember: transform in your script is the player transform not the fireball transform.) Check https://docs.unity3d.com/ScriptReference/Quaternion.LookRotation.html. LookRotation will return the rotation based on player's forward and up vectors.
GameObject newSpell = Instantiate(Spell);
newSpell.transform.position = transform.position;
newSpell.transform.rotation = Quaternion.LookRotation(transform.forward, transform.up);
Not part of your question, but I would also suggest letting the fireball fly in the forward direction of itself not the player (as this leaves more room for later modifications)
rb.AddForce(newSpell.transform.forward * SpellSpeed);

Related

How do i replace my game object's current position with a new one?

I wanted to make a vertically scrolling background with 3D assets (2D pictures works fine, but i wanted the cool lighting effect), and i kept failing doing something i though would be so simple.
so here's my current progress:
public Vector3 target;
private Transform Top_Top_Left_Rescroll;
void Start (){
target = GameObject.FindGameObjectWithTag ("Top_Top_Left_Rescroll").GetComponent<Transform>();
}
void Update () {
if (gameObject.transform.position.y <= -12) {
gameObject.transform.position = new Vector3 (target.x, target.y, target.z);
}
}
}
The object resets it's position to 0 after the if statement (the rotation and scale weren't affected), and i ran out of ideas to do what i want.
You are passing a Transform to a Vector3.
try :
target = GameObject.FindGameObjectWithTag("Top_Top_Left_Rescroll").transform.position;
ps: I'm not sure if you really want your target position to never change, but you are passing it's value during Start() so you will always place your gameObject in every frame at the same initial position.

GameObject Follow cursor yet also follows enemies?

I'm making a simple character that follows the player's cursor. What I also want is for when the game object "enemy" appears the character then goes to that location to alert the player. Once the enemy is gone the character continues to follow the cursor like normal. Is there a reason why my script won't work. How else can I paraphrase it?
public class FollowCursor : MonoBehaviour
{
void Update ()
{
//transform.position = Camera.main.ScreenToWorldPoint( new Vector3(Input.mousePosition.x,Input.mousePosition.y,8.75f));
if (gameObject.FindWithTag == "Enemy")
{
GameObject.FindWithTag("Enemy").transform.position
}
if (gameObject.FindWithTag != "Enemy")
{
transform.position = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x,Input.mousePosition.y,8.75f));
}
}
}
You are not using FindWithTag correctly, as it is a method that takes a string as parameter you need to use it like this:
GameObject.FindwithTag("Something") as stated in the Unity scripting API
Now to apply this to your code you would need to do the following to set your players position based on wether or not an enemy is found (assuming this script is on your actual player object):
if(GameObject.FindWithTag("Enemy"))
{
//If an enemy is found with the tag "Enemy", set the position of the object this script is attatched to to be the same as that of the found GameObject.
transform.position = GameObject.FindWithTag("Enemy").transform.position;
}
else
{
//when no enemy with the tag "Enemy" is found, set this GameObject its position to the the same as that of the cursor
transform.position = Camera.main.ScreenToWorldPoint( new Vector3(Input.mousePosition.x,Input.mousePosition.y,8.75f));
}
However this code will just snap your player instantly to the position of the found Enemy. If this is not the desired behaviour you could use a function like Vector3.MoveTowards instead to make the player move to it gradually.
This code also has room for optimisation as searching for a GameObject every update frame is not the ideal solution. But for now it should work.
I'm going to code coding all the function for you, I'm not pretty sure about the beavihour of your code, I understand a gameobject will be attached to the mouse position, so not really following....
Vector3 targetPosition;
public float step = 0.01f;
void Update()
{
//if there is any enemy "near"/close
//targetPosition = enemy.position;
//else
//targetPosition = MouseInput;
transform.position = Vector3.MoveTowards(transform.position, targetPosition , step);
}
For the f you can use a SphereCast and from the enemies returned get the closest one.

Smooth Camera Follow with Voxel Based Sphere

I am very new to Unity and just got done yesterday following the Roller Ball example on the learn page here at Unity3d.
To practice what I have learned I wanted to try and recreate something similar using my own art and making the game different. I have been playing around with Voxel Art and I am using MagicaVoxel to create my assests. I created the walls, the ground etc.. and all is well.
Then came the player object, the sphere. I created one as close to a sphere as possible with magicaVoxel and it rolls fine. However, when using a script to have the camera follow the object it runs into issues.
If I don't constrain the Y axis then I will get bouncing and as far as the x and z axis I get kind of a Flat Tire effect. Basically the camera doesn't follow smoothly it bounces around, stop go etc...
I have tried making the collider larger then the sphere and even using the position of the collider vs the object itself. I have also tried putting the code in Update / FixedUpdate / LateUpdate. What is the proper way to fix or address something like this? Here is my scripts below:
Camera Controller:
public class CamController : MonoBehaviour {
public GameObject player;
private Vector3 offset;
void Start ()
{
// Get the distance between the player ball and camera.
offset = this.transform.position - player.transform.position;
}
void LateUpdate ()
{
this.transform.position = player.transform.position + offset;
}
}
Player Controller:
public class PlayerController : MonoBehaviour {
public float _speed;
void FixedUpdate()
{
// Get input from keyboard.
float _hoz = Input.GetAxis("Horizontal");
float _ver = Input.GetAxis("Vertical");
// Create a vector3 based on input from keyboard.
Vector3 _move = new Vector3(_hoz, 0.0f, _ver);
// Apply force to the voxel ball
this.GetComponent<Rigidbody>().AddForce(_move * _speed);
}
}
Thanks for any help in advance.
You can use the SmoothFollow Script of Unity it self for getting smooth follow of camera.
Here are the steps how you can get the script:
1) Assets->Import Package->Scripts.
2) At the dialog that appears select all the scripts, or just the smooth follow one and hit Import button.
3) Now this script is in your project, and you can attach it to the camera.
Hope this will help you...
Best,
Hardik.

Moving something rotated on a custom pivot Unity

I've created an arm with a custom pivot in Unity which is essentially supposed to point wherever the mouse is pointing, regardless of the orientation of the player. Now, this arm looks weird when pointed to the side opposite the one it was drawn at, so I use SpriteRenderer.flipY = true to flip the sprite and make it look normal. I also have a weapon at the end of the arm, which is mostly fine as well. Now the problem is that I have a "FirePoint" at the end of the barrel of the weapon, and when the sprite gets flipped the position of it doesn't change, which affects particles and shooting position. Essentially, all that has to happen is that the Y position of the FirePoint needs to become negative, but Unity seems to think that I want the position change to be global, whereas I just want it to be local so that it can work with whatever rotation the arm is at. I've attempted this:
if (rotZ > 40 || rotZ < -40) {
rend.flipY = true;
firePoint.position = new Vector3(firePoint.position.x, firePoint.position.y * -1, firePoint.position.z);
} else {
rend.flipY = false;
firePoint.position = new Vector3(firePoint.position.x, firePoint.position.y * -1, firePoint.position.z);
}
But this works on a global basis rather than the local one that I need. Any help would be much appreciated, and I hope that I've provided enough information for this to reach a conclusive result. Please notify me should you need anything more. Thank you in advance, and have a nice day!
You can use RotateAround() to get desired behaviour instead of flipping stuff around. Here is sample code:
public class ExampleClass : MonoBehaviour
{
public Transform pivotTransform; // need to assign in inspector
void Update()
{
transform.RotateAround(pivotTransform.position, Vector3.up, 20 * Time.deltaTime);
}
}

Unity Android:Rigidbody

I'm working with an android project in Unity 3d.
I would to roll the sphere at the surface of a cube.
However, when I clicked the play button it returns error message:
Assets/Scripts/Player.js(4,1): BCE0005: Unknown identifier: 'rigidBody'.
My code:
function Start () {
rigidBody.velocity.x=15;
}
Rigidbody components has been already added to the sphere.
I would like to seek solution to the error generated.
I don't know if you've set a GetComponent variable on the rigidbody, but you may have to strip the case out of that.
For example:
rigidBody.velocity.x=15;
would be:
rigidbody.velocity.x=15;
Hope that helps.
First, it's "rigidbody" not "rigidBody"
Second, starting with Unity 5 + something you cannot use "rigidbody"
anymore, so you have to use GetComponent
Resuming, to use "rigidBody" as it is, you have to initialize it first like others answered you already:
//link you rigidbody here:
public Rigidbody rigidBody;
function Start() {
//Or if the script is on the GameObject that has the rigidbody component:
//rigidBody = GetComponent<Rigidbody>();
rigidBody.velocity=new Vector2(15,0);
}
I think you forgot to initialize a Rigidbody. Also you cannot assign a velocity like this because rigidBody.velocity.x is a read-only value.This code might help you:
public Rigidbody rigidBody;
function Start(){
rigidBody.velocity=new Vector2(15,0);
}
You haven't initialized the variable "rigidBody".
I don't think that's your objective though.
If you have the script added to the sphere as a component, you don't have to use getComponent. Instead it's going to be just:
"Rigidbody.velocity.x=15;"
You might have to use a "new Vector3(x,y,z);" to pass the new velocity on. In that case the code would look like this:
Rigidbody.velocity = new Vector3(15,Rigidbody.velocity.y, Rigidbody.velocity.z)*
I'm working in 2D right now, so my parameters of Vector3 might be off.
I thought Rigedbody was correct, but it might be rigidbody - see above.
In any case, don't forget your colliders. Ridged bodies don't automatically collide with other objects, but they are subject to gravity. Once I finally figured that out, I just dropped my character 20 feet onto pavement out of joy. Rendering blood is surprisingly easy if you're not that picky.
you need add rigidbody components in inspectors first then :
Rigidbody sphereRigidbody;
function Awake(){
sphereRigidbody = GetComponent<Rigidbody>();
sphereRigidbody.velocity = new Vector3(15,0,0);
}
for c#
You might want to cache it first.
private Rigidbody rigidbodyCached;
//cache
void Start(){
rigidbodyCached = this.GetComponent<Rigidbody>();
}
//for velocity movements use FixedUpdate instead of Update
void FixedUpdate(){
rigidbodyCached.velocity = new Vector3(15,0,0);
}
if you working with unity less than 5 (I guess) you have access to use components of game objects like rigidbody or audiosource but in unity 5 and later you need to add a reference to that in neither in awake or start function like this code
private Rigidbody rb;
void Start() {
rb = GetComponent<Rigidbody>();
// AND AFTER YOU ADDED THE REFERENCE FOR RIGIDBODY
// THEN CHANGE THE VELOCITY LIKE THIS
rb.velocity.x = 20;
}