I am working on a Unity project using google cardboard, basing my design on Cardboard Catapult, cardboard magnet to make a ball jump and it works the first time, but whenever the game restarts, using Application.LoadLevel(), the ball doesn’t jump anymore; it just glitches. I used this script. I have tested this script (Magnet Sensor Script) with a test application where whenever the magnet is pulled, the text will change color and it works all the time. Here’s my Ball Control Script (the script I called the Magnet Sensing):
#pragma strict
var rotationSpeed = 100;
var jumpHeight = 8;
var Hit01 : AudioClip;
var Hit02 : AudioClip;
var Hit03 : AudioClip;
var distToGround : float;
function Start () {
// Getting the distance from the center to the ground.
distToGround = collider.bounds.extents.y;
}
function Update ()
{
//Handle ball rotation.
var rotation : float = Input.GetAxis(“Horizontal”) * rotationSpeed;
rotation *= Time.deltaTime;
rigidbody.AddRelativeTorque (Vector3.back * rotation);
MagnetSensor.OnMagnetPull += JumpOnMagnet; //important
}
function JumpOnMagnet () { //important
rigidbody.velocity.y = jumpHeight; //important
} //important
function IsGrounded () : boolean { //Check if we are on the ground. Return true if we are else return null.
return Physics.Raycast(transform.position, -Vector3.up, distToGround + 0.1);
}
function OnCollisionEnter () {
var theHit = Random.Range(0, 3);
if (theHit == 0)
{
audio.clip = Hit01;
}
else if (theHit == 1)
{
audio.clip = Hit02;
}
else {
audio.clip = Hit03;
}
audio.pitch = Random.Range (0.9,1.1);
audio.Play();
}
Here’s my script for the restart:
#pragma strict
var maxFallDistance = -10;
private var isRestarting = false;
var level : String;
var GameOverSound : AudioClip;
function Update ()
{
if (transform.position.y <= maxFallDistance)
{
if (isRestarting == false)
{
RestartLevel();
}
}
}
function RestartLevel () {
isRestarting = true;
audio.pitch = 1;
audio.clip = GameOverSound;
audio.Play();
yield WaitForSeconds (audio.clip.length);
Application.LoadLevel(level);
}
Please let me know what the possible issues could be and how I can fix them. Also, I’d appreciate if you can point me to any website or resource that can help.
Don't do MagnetSensor.OnMagnetPull += JumpOnMagnet; in the Update() function. Call it in Start(), so it is only added once.
Also, you should add an OnDestroy() function and call MagnetSensor.OnMagnetPull -= JumpOnMagnet; in it.
Related
I am trying to create a simple Infinite Runner game on Unity and ran into a problem. The task is to make a ball spawn on the floor and immediately begin to roll to the left towards the Player. I have tried a number of ways to implement it, but it does not seem to work. Here is my most recent attempt:
public class ObstaclePool : MonoBehaviour {
public GameObject columnPrefab;
public GameObject ballPrefab;
public int obstaclePoolSize = 5;
public float spawnRate = 3f;
private GameObject[] obstacles;
private int currentObstacle = 0;
private Vector2 objectPoolPosition = new Vector2(-15, -25);
private float timeSinceLastSpawned;
private float spawnXPosition;
private bool hasCalled = false;
private int dice;
bool beforeBall = false;
// Use this for initialization
void Start () {
timeSinceLastSpawned = 0f;
SetupObstacles();
}
private void SetupObstacles()
{
obstacles = new GameObject[obstaclePoolSize];
for (int i = 0; i < obstaclePoolSize; i++)
{
dice = Random.Range(1, 3);
if (dice == 1)
{
obstacles[i] = (GameObject)Instantiate(columnPrefab, objectPoolPosition, Quaternion.identity);
}
else if (dice == 2)
{
obstacles[i] = (GameObject)Instantiate(ballPrefab, objectPoolPosition, Quaternion.identity);
}
}
}
// Update is called once per frame
void Update () {
timeSinceLastSpawned += Time.deltaTime;
if (GameControl.instance.gameOver == false && timeSinceLastSpawned >= spawnRate)
{
timeSinceLastSpawned = 0f;
if (hasCalled == false)
{
spawnXPosition = 10f;
hasCalled = true;
}
else
{
spawnXPosition = Random.Range(6f, 10f);
}
if (obstacles[currentObstacle].transform.tag == "Ball")
{
spawnXPosition = Random.Range(9f, 10f);
obstacles[currentObstacle].transform.position = new Vector2(spawnXPosition, -1.84f);
ballPrefab.GetComponent<Rigidbody2D>().AddForce(new Vector2(-100f, 0) * 5);
beforeBall = true;
}
else {
if (beforeBall == true)
{
spawnXPosition = Random.Range(9f, 10f);
beforeBall = false;
}
obstacles[currentObstacle].transform.position = new Vector2(spawnXPosition, -7.08f);
Debug.Log(spawnXPosition);
}
currentObstacle++;
if (currentObstacle >= obstaclePoolSize)
{
currentObstacle = 0;
SetupObstacles();
hasCalled = false;
}
}
}
}
For a quick explanation of my code: I have an array of size 5. It holds the obstacles that I have created. When deciding what to put inside the array, I generated a random number (1 or 2). If it's a 1, I put in a column. If it's a 2, I put in a ball. These obstacles are spawned off-screen. Then, I move them in the actual scene after using random number to determine the X position.
This part in particular is where I try to implement it:
if (obstacles[currentObstacle].transform.tag == "Ball")
{
spawnXPosition = Random.Range(9f, 10f);
obstacles[currentObstacle].transform.position = new Vector2(spawnXPosition, -1.84f);
ballPrefab.GetComponent<Rigidbody2D>().AddForce(new Vector2(-100f, 0) * 5);
beforeBall = true;
}
I may have some remnants of stuff that I have been testing out, so some of the code may seem redundant and messy.
I also tried using Translate and Velocity with no success. I also have a ScrollingObject code and a RepeatingBackground code. I placed the ScrollingObject code in the Ball prefab too. (Also, tried taking it out -> ball rolls to the right). These codes come from the Unity tutorial.
RepeatingBackground:
public class RepeatingBackground : MonoBehaviour {
private BoxCollider2D groundCollider;
private float groundHorizontalLength;
// Use this for initialization
private void Awake () {
groundCollider = GetComponent<BoxCollider2D>();
groundHorizontalLength = groundCollider.size.x;
}
// Update is called once per frame
private void Update () {
if (transform.position.x < -groundHorizontalLength)
{
RepositionBackground();
}
}
private void RepositionBackground()
{
Vector2 groundOffSet = new Vector2(groundHorizontalLength * 2f, 0);
transform.position = (Vector2)transform.position + groundOffSet;
}
}
ScrollingObjects:
public class ScrollingObject : MonoBehaviour {
private Rigidbody2D rb2d;
// Use this for initialization
void Start () {
rb2d = GetComponent<Rigidbody2D>();
rb2d.velocity = new Vector2(GameControl.instance.scrollSpeed, 0);
}
// Update is called once per frame
void Update () {
if (GameControl.instance.gameOver == true)
{
rb2d.velocity = Vector2.zero;
}
}
}
It looks like you simply named the wrong object in your first example.
if (obstacles[currentObstacle].transform.tag == "Ball")
{
spawnXPosition = Random.Range(9f, 10f);
obstacles[currentObstacle].transform.position = new Vector2(spawnXPosition, -1.84f);
ballPrefab.GetComponent<Rigidbody2D>().AddForce(new Vector2(-100f, 0) * 5);
beforeBall = true;
}
Notice how here you added the force to the prefab, not an instantiated version of the prefab.
I played around a bit more and got it to work. I just wrote another script that added force to the object. I still do not understand why my original way did not work though.
I'm working on a project in Unity and I've created a script called DeerHater that targets the transform and controller of an object that enters the specified area. The script by itself works but it's connected to a parent object that has it's controller attached and that controller is supposed to access the variables of DeerHater and then do specified functions.
The problem is that the variables in controller doesn't change from empty to the variables that has changed in DeerHater since the desired object entered the trigger and it showups these two errors:
NullReferenceException: Object reference not set to an instance of an object
MissingFieldException: DeerController.targetDeer
I can't really see where the problem is since I'm a total beginner, could anyone tell me why wouldn't it acces DeerHater variables?
BearController script (parent object):
var distanceDeer : float;
var deerHater : DeerHater;
var deer : GameObject = null;
var targetDeer : Transform;
var isFollowing : boolean = false;
var center : Transform;
var deerKilled : boolean = false;
function Start()
{
deerHater = GameObject.Find("DeerHater").GetComponent(DeerHater);
}
function Update()
{
deer = deerHater.deerController.
targetDeer = deerHater.stupidDeer;
distanceDeer = Vector3.Distance(deerHater.stupidDeer.position, transform.position);
if(deerHater.collisionDeer == true)
{
ChaseDeer();
if(distanceDeer < attackRange)
{
deer.health = -0.1;
deerKilled = true;
}
if(deerKilled == true)
{
GoBack();
deerKilled = false;
}
}
}
function ChaseDeer()
{
var rotation = Quaternion.LookRotation(deerHater.stupidDeer.position - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * damping);
moveSpeed = 6;
animation.Play("Run");
animation["Run"].speed = 1.25;
moveDirection = transform.forward;
moveDirection *= moveSpeed;
isFollowing = true;
moveDirection.y -= gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
}
And here's the DeerHater script:
#pragma strict
var stupidDeer : Transform;
var deerController : DeerController;
public var collisionDeer : boolean = false;
function OnTriggerEnter(col : Collider)
{
if(col.gameObject.tag == "Deer")
{
collisionDeer = true;
stupidDeer = col.gameObject.transform;
deerController = col.gameObject.GetComponent(DeerController);
}
}
function OnTriggerExit(col : Collider)
{
if(col.gameObject.tag == "Deer")
{
collisionDeer = false;
stupidDeer = null;
deerController = null;
}
}
Thanks in advance!
I've managed to fix this by placing DeerHater code inside the BeerController and moving the deer variables from global variables to if(deerCollision == true).
I'm creating a project for my school and it was going pretty good until now. I've searched for an answer for nearly an hour and still couldn't find anything (wrong tags?).
The thing is that I want to show the name of the item that player is hitting with raycast. I tried this but sadly it's not working:
#pragma strict
var rayLength : int = 10;
private var inventory : Inventory;
private var guiShow : boolean = false;
var bush : GameObject;
var player : GameObject;
function Start()
{
inventory = GameObject.Find("First Person Controller").GetComponent(Inventory);
}
function Update()
{
var hit : RaycastHit;
var forward = transform.TransformDirection(Vector3.forward);
if(Physics.Raycast(transform.position, forward, hit, rayLength))
{
if(hit.collider.gameObject.tag == "Wood")
{
guiShow = true;
if(Input.GetKeyDown("e"))
{
inventory.wood++;
Destroy(hit.collider.gameObject);
guiShow = false;
}
}
else if(hit.collider.gameObject.tag == "Sticks")
{
guiShow = true;
if(Input.GetKeyDown("e"))
{
inventory.stick++;
Destroy(hit.collider.gameObject);
guiShow = false;
}
}
else if(hit.collider.gameObject.tag == "BushFull")
{
guiShow = true;
bush = (hit.collider.gameObject);
if(Input.GetKeyDown("e"))
{
inventory.berry += 5;
bush.GetComponent(BushController).berriesTaken = true;
guiShow = false;
}
}
else
{
guiShow = false;
}
}
else
{
guiShow = false;
}
}
function OnGUI()
{
if(guiShow == true)
{
GUI.Box(Rect(Screen.width / 2, Screen.height / 2, 100, 25), "Pick up" + hit.collider.gameObject);
}
}
If anyone knows answer - please help me. Thanks in advance!
Just use hit.collider.name to retrieve the gameObject's name. If that doesn't work (which I'm 99% sure it will), use hit.collider.gameObject.name
Your code is a little tricky because maybe it would be a greater idea not to use the OnGUI() method. It's easier to call a custom method from update when the raycast hit the player.
One example of an easier implementation is the following:
function Update()
{
var hit : RaycastHit;
var forward = transform.TransformDirection(Vector3.forward);
if(Physics.Raycast(transform.position, forward, hit, rayLength))
{
Debug.Log (hit.collider.gameObject.name); //Shows the hittenGo in the console
drawColliderName(hit.collider.gameObject.name);
if (hit.collider.gameObject.tag == "Woods")
{
//do Woods tuff
}
else if (hit.collider.gameObject.tag == "Sticks")
{
//do Sticks stuff
}
else if (hit.collider.gameObject.tag == "BushFull")
{
//do BushFull stuff
}
}
}
Of course you have to implement the method drawColliderName where you must draw the Collider name on the GUI.
If you just want your code to work, in the OnGUI() you have to call name variable, like in the Debug.Log call of my code, this is just calling hit.collider.gameObject.name instead of hit.collider.gameObject
I've got a script from a tutorial that makes my player jump when you press a button but I don't know how to configure how high it jumps. Heres the code:
var before : Sprite;
var after : Sprite;
var isGrounded : boolean;
var Animator : Animator;
var character : GameObject;
var jump : float = 0;
var jumpSpeed : float = 5;
var jumpTimer : float = 0;
function Start () {
isGrounded = true;
}
function Update () {
Animator.SetBool("isGrounded", isGrounded);
if(jump == 1) {
jumpTimer = jumpTimer + 1;
}
if(jumpTimer >= 50) {
jumpTimer = 0;
jump = 0;
}
}
function OnMouseDown () {
isGrounded = false;
GetComponent(SpriteRenderer).sprite = after;
if(jump == 0) {
character.GetComponent(Rigidbody2D).velocity.y = jumpSpeed;
jump = 1;
}
yield WaitForSeconds (0.5);
isGrounded = true;
}
function OnMouseUp () {
GetComponent(SpriteRenderer).sprite = before;
}
I tried lowering the floats for jump/jumpspeed/jumptimer but it just won't work. Any ideas?
Placing my comment into an answer for anyone else using the same tutorial and having the same issue.
The line below is used to alter the players y velocity.
character.GetComponent(Rigidbody2D).velocity.y = jumpSpeed;
In order to change the jump height of the player, you will need to alter the jumpSpeed variable.
Note
If you are altering the jumpSpeed variable at the top of the script and it isn't changing, it is because the value in the inspector overrides the value entered at the top of the script.
OVERALL GOAL: Have the camera change target to the selected car
I'm new to the unity game engine and got a bit of a problem.
So, I have a successful car selector which changes between cars and starts the match with that car. Everything there works. The only issue is that my "CarCameraScript" has a transform variable which is always 1 of the 3 cars. I want it to change dependant on the selected car.
Here is the look at the code of the CarCameraScript
#pragma strict
var car : Transform;
var distance: float = 6.4;
var height: float = 1.4;
var rotationDamping : float = 3.0;
var heightDamping: float = 2.0;
var zoomRatio : float = 0.5;
var DefaultFOV : float = 60;
private var rotationVector : Vector3;
function Start () {
}
function LateUpdate () {
var wantedAngel = rotationVector.y;
var wantedHeight = car.position.y + height;
var myAngel = transform.eulerAngles.y;
var myHeight = transform.position.y;
myAngel = Mathf.LerpAngle(myAngel,wantedAngel,rotationDamping*Time.deltaTime);
myHeight = Mathf.Lerp(myHeight,wantedHeight,heightDamping*Time.deltaTime);
var currentRotation = Quaternion.Euler(0,myAngel,0);
transform.position = car.position;
transform.position -= currentRotation*Vector3.forward*distance;
transform.position.y = myHeight;
transform.LookAt(car);
}
function FixedUpdate () {
var localVilocity = car.InverseTransformDirection(car.rigidbody.velocity);
if (localVilocity.z<-0.5) {
rotationVector.y = car.eulerAngles.y + 180;
} else {
rotationVector.y = car.eulerAngles.y;
}
var acc = car.rigidbody.velocity.magnitude;
camera.fieldOfView = DefaultFOV + acc*zoomRatio;
}
This is what it looks like on the side panel.
http://i.stack.imgur.com/lYJP7.jpg
The area that says none (transform) is the place that should be variable dependant on the currently selected car.
Now, Here is my other script being the CharacterSelectScript
#pragma strict
//this is the currently selected Player. Also the one that will be saved to PlayerPrefs
var selectedPlayer : int = 0;
function Update()
{
if (Input.GetMouseButtonUp (0)) {
var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
var hit : RaycastHit;
if (Physics.Raycast (ray, hit, 100))
{
// The pink text is where you would put the name of the object you want to click on (has attached collider).
if(hit.collider.name == "Player1")
SelectedCharacter1(); //Sends this click down to a function called "SelectedCharacter1(). Which is where all of our stuff happens.
if(hit.collider.name == "Player2")
SelectedCharacter2();
if(hit.collider.name == "Player3")
SelectedCharacter3();
}
else
{
return;
}
}
}
function SelectedCharacter1() {
Debug.Log ("Character 1 SELECTED"); //Print out in the Unity console which character was selected.
selectedPlayer = 1;
PlayerPrefs.SetInt("selectedPlayer", (selectedPlayer));
}
function SelectedCharacter2() {
Debug.Log ("Character 2 SELECTED");
selectedPlayer = 2;
PlayerPrefs.SetInt("selectedPlayer", (selectedPlayer));
}
function SelectedCharacter3() {
Debug.Log ("Character 3 SELECTED");
selectedPlayer = 3;
PlayerPrefs.SetInt("selectedPlayer", (selectedPlayer));
}
How would I get it so that the SelectedPlayer changes the transform in the first script?
Any ideas?
I also have the prefab script which probably isnt important.
Also, should I join both scripts into one?
OVERALL GOAL: Have the camera change target to the selected car