- Home /
NullReferenceException: Object reference not set to an instance of an object
Hi everyone, i had an error: NullReferenceException: Object reference not set to an instance of an object CarControl.FixedUpdate () (at Assets/Standard Assets/CarControl.cs:48)
What i'm trying to do is have the Car be controlled by a joystick. The reason im using "Input.GetAxisRaw("Horizontal") + jsScript.position.x;" is so I can have the car controlled by a keyboard or a joystick.
Thank you for your help! Im 14 so basic explanations would be great. :)
Extra Info: The reason I am doing this is because im creating an smart phone/flash so thats why im using 2 inputs. :)
using UnityEngine;
using System.Collections;
public class CarControl : MonoBehaviour
{
public GameObject RightWheel;
public GameObject LeftWheel;
//public GameObject RJS;
public GameObject LJS;
//create a variable to access the JavaScript script
private Joystick jsScript;
void Awake()
{
//Get the JavaScript component
jsScript = this.GetComponent<Joystick>();//Don't forget to place the JS file inside the 'Standard Assets' folder
}
void Start()
{
Vector3 center = rigidbody.centerOfMass;
center.y -= 1;
rigidbody.centerOfMass = center;
}
int walkSpeed = 30;
void FixedUpdate ()
{
float h = Input.GetAxisRaw("Horizontal") + jsScript.position.x;
//Debug.Log(jsScript.position.x);
JointMotor motor = LeftWheel.hingeJoint.motor;
motor.force = (h!=0?1:0) * 40;//30
motor.freeSpin = true;//true
motor.targetVelocity = -h * 5000;//4000
if (Input.GetKey("space")){
rigidbody.AddForce (99, 100, 0); }
LeftWheel.hingeJoint.useMotor = h != 0;
LeftWheel.hingeJoint.motor = motor;
RightWheel.hingeJoint.useMotor = h != 0;
RightWheel.hingeJoint.motor = motor;
rigidbody.AddRelativeTorque(0, 0, -h * 4000);//3000
// flip the car
if (Input.GetKey("w")||Input.GetKey("up"))
{
float deltaAngle = Mathf.DeltaAngle(transform.eulerAngles.z, 0);
if (Mathf.Abs(deltaAngle) > 10)
{
rigidbody.AddTorque(0, 0, deltaAngle * deltaAngle * deltaAngle, ForceMode.VelocityChange);
}
}
}
}
The referenced script is:
//////////////////////////////////////////////////////////////
// Joystick.js
// Penelope iPhone Tutorial
//
// Joystick creates a movable joystick (via GUITexture) that
// handles touch input, taps, and phases. Dead zones can control
// where the joystick input gets picked up and can be normalized.
//
// Optionally, you can enable the touchPad property from the editor
// to treat this Joystick as a TouchPad. A TouchPad allows the finger
// to touch down at any point and it tracks the movement relatively
// without moving the graphic
//////////////////////////////////////////////////////////////
#pragma strict
@script RequireComponent( GUITexture )
// A simple class for bounding how far the GUITexture will move
class Boundary
{
var min : Vector2 = Vector2.zero;
var max : Vector2 = Vector2.zero;
}
static private var joysticks : Joystick[]; // A static collection of all joysticks
static private var enumeratedJoysticks : boolean = false;
static private var tapTimeDelta : float = 0.3; // Time allowed between taps
var touchPad : boolean; // Is this a TouchPad?
var touchZone : Rect;
var deadZone : Vector2 = Vector2.zero; // Control when position is output
var normalize : boolean = false; // Normalize output after the dead-zone?
var position : Vector2; // [-1, 1] in x,y
var tapCount : int; // Current tap count
private var lastFingerId = -1; // Finger last used for this joystick
private var tapTimeWindow : float; // How much time there is left for a tap to occur
private var fingerDownPos : Vector2;
private var fingerDownTime : float;
private var firstDeltaTime : float = 0.5;
private var gui : GUITexture; // Joystick graphic
private var defaultRect : Rect; // Default position / extents of the joystick graphic
private var guiBoundary : Boundary = Boundary(); // Boundary for joystick graphic
private var guiTouchOffset : Vector2; // Offset to apply to touch input
private var guiCenter : Vector2; // Center of joystick
function Start()
{
// Cache this component at startup instead of looking up every frame
gui = GetComponent( GUITexture );
// Store the default rect for the gui, so we can snap back to it
defaultRect = gui.pixelInset;
defaultRect.x += transform.position.x * Screen.width;// + gui.pixelInset.x; // - Screen.width * 0.5;
defaultRect.y += transform.position.y * Screen.height;// - Screen.height * 0.5;
transform.position.x = 0.0;
transform.position.y = 0.0;
if ( touchPad )
{
// If a texture has been assigned, then use the rect ferom the gui as our touchZone
if ( gui.texture )
touchZone = defaultRect;
}
else
{
// This is an offset for touch input to match with the top left
// corner of the GUI
guiTouchOffset.x = defaultRect.width * 0.5;
guiTouchOffset.y = defaultRect.height * 0.5;
// Cache the center of the GUI, since it doesn't change
guiCenter.x = defaultRect.x + guiTouchOffset.x;
guiCenter.y = defaultRect.y + guiTouchOffset.y;
// Let's build the GUI boundary, so we can clamp joystick movement
guiBoundary.min.x = defaultRect.x - guiTouchOffset.x;
guiBoundary.max.x = defaultRect.x + guiTouchOffset.x;
guiBoundary.min.y = defaultRect.y - guiTouchOffset.y;
guiBoundary.max.y = defaultRect.y + guiTouchOffset.y;
}
}
function Disable()
{
gameObject.active = false;
enumeratedJoysticks = false;
}
function ResetJoystick()
{
// Release the finger control and set the joystick back to the default position
gui.pixelInset = defaultRect;
lastFingerId = -1;
position = Vector2.zero;
fingerDownPos = Vector2.zero;
if ( touchPad )
gui.color.a = 0.025;
}
function IsFingerDown() : boolean
{
return (lastFingerId != -1);
}
function LatchedFinger( fingerId : int )
{
// If another joystick has latched this finger, then we must release it
if ( lastFingerId == fingerId )
ResetJoystick();
}
function Update()
{
if ( !enumeratedJoysticks )
{
// Collect all joysticks in the game, so we can relay finger latching messages
joysticks = FindObjectsOfType( Joystick ) as Joystick[];
enumeratedJoysticks = true;
}
var count = Input.touchCount;
// Adjust the tap time window while it still available
if ( tapTimeWindow > 0 )
tapTimeWindow -= Time.deltaTime;
else
tapCount = 0;
if ( count == 0 )
ResetJoystick();
else
{
for(var i : int = 0;i < count; i++)
{
var touch : Touch = Input.GetTouch(i);
var guiTouchPos : Vector2 = touch.position - guiTouchOffset;
var shouldLatchFinger = false;
if ( touchPad )
{
if ( touchZone.Contains( touch.position ) )
shouldLatchFinger = true;
}
else if ( gui.HitTest( touch.position ) )
{
shouldLatchFinger = true;
}
// Latch the finger if this is a new touch
if ( shouldLatchFinger && ( lastFingerId == -1 || lastFingerId != touch.fingerId ) )
{
if ( touchPad )
{
gui.color.a = 0.15;
lastFingerId = touch.fingerId;
fingerDownPos = touch.position;
fingerDownTime = Time.time;
}
lastFingerId = touch.fingerId;
// Accumulate taps if it is within the time window
if ( tapTimeWindow > 0 )
tapCount++;
else
{
tapCount = 1;
tapTimeWindow = tapTimeDelta;
}
// Tell other joysticks we've latched this finger
for ( var j : Joystick in joysticks )
{
if ( j != this )
j.LatchedFinger( touch.fingerId );
}
}
if ( lastFingerId == touch.fingerId )
{
// Override the tap count with what the iPhone SDK reports if it is greater
// This is a workaround, since the iPhone SDK does not currently track taps
// for multiple touches
if ( touch.tapCount > tapCount )
tapCount = touch.tapCount;
if ( touchPad )
{
// For a touchpad, let's just set the position directly based on distance from initial touchdown
position.x = Mathf.Clamp( ( touch.position.x - fingerDownPos.x ) / ( touchZone.width / 2 ), -1, 1 );
position.y = Mathf.Clamp( ( touch.position.y - fingerDownPos.y ) / ( touchZone.height / 2 ), -1, 1 );
}
else
{
// Change the location of the joystick graphic to match where the touch is
gui.pixelInset.x = Mathf.Clamp( guiTouchPos.x, guiBoundary.min.x, guiBoundary.max.x );
gui.pixelInset.y = Mathf.Clamp( guiTouchPos.y, guiBoundary.min.y, guiBoundary.max.y );
}
if ( touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled )
ResetJoystick();
}
}
}
if ( !touchPad )
{
// Get a value between -1 and 1 based on the joystick graphic location
position.x = ( gui.pixelInset.x + guiTouchOffset.x - guiCenter.x ) / guiTouchOffset.x;
position.y = ( gui.pixelInset.y + guiTouchOffset.y - guiCenter.y ) / guiTouchOffset.y;
}
// Adjust for dead zone
var absoluteX = Mathf.Abs( position.x );
var absoluteY = Mathf.Abs( position.y );
if ( absoluteX < deadZone.x )
{
// Report the joystick as being at the center if it is within the dead zone
position.x = 0;
}
else if ( normalize )
{
// Rescale the output after taking the dead zone into account
position.x = Mathf.Sign( position.x ) * ( absoluteX - deadZone.x ) / ( 1 - deadZone.x );
}
if ( absoluteY < deadZone.y )
{
// Report the joystick as being at the center if it is within the dead zone
position.y = 0;
}
else if ( normalize )
{
// Rescale the output after taking the dead zone into account
position.y = Mathf.Sign( position.y ) * ( absoluteY - deadZone.y ) / ( 1 - deadZone.y );
}
}
function FixedUpdate(){
Debug.Log(position.x);
}
Answer by farray · Aug 10, 2013 at 11:42 PM
I'm surprised your scripts are even compiling if both CarControl.cs and your Joystick.js files are both in the Standard Assets directory. The reason to put Joystick.js in "Standard Assets" is so that Unity compiles the JS before it attempts to compile the C#. In my Unity install (4.1.4f1 Mac), Unity won't even allow the GetComponent()
call if both files are in Standard Assets.
To debug your error further, put a breakpoint at the offending line and see if "jsScript" is null. If it is null, put a breakpoint after the GetComponent
call and see if it properly got the component when the CarControl script awoke.
The other thing to check is to make sure that you added the JoyStick.cs component to the same gameobject as your CarControl component.
Answer by Joyrider · Aug 10, 2013 at 10:55 PM
Like the error suggests, it is a problem at line 48. Two things
NULL REFERENCE EXCEPTION
Empty variable (=null) + accessing its property = Null Reference Exception
A null reference exception means you have an empty variable on which you're trying to do something. You're reserved a slot to put the reference to an object, but you've got nothing in it. So when you try to access a property of it, Unity generates this error.
e.g. a gameobject of which you want to know the name. If the gameobject variable is empty, accessing his name will generate this kind of error. You can't access the name of something that doesn't exist.
Here specifically, my guess is, the problem is with your jsScript variable. Are you sure the Joystick script you're trying to acquire in your Awake(), is being found?
Using Null-checks in your code, when you are not 100% sure a variable will never be empty is always a good idea:
if(variableName != null)
//do your thing with that variable
if needed you can add an else statement to output an error (which thankfully did not occur) in your logs
if(variableName != null)
//do your thing with that variable
else
Debug.LogError("variableName was null!");
.
INTER-LANGUAGE COMMUNICATION & COMPILATION ORDER
From the error, I can also see your C# script is in Standard Assets folder, and I'm guessing so is your Joystick script. You have to take your c# script out of the Standard Assets folder for this to work.
Working with two different languages is basicaly not a good idea. My guess is you're modifying existing code, and thus using whatever is available to you. But if you can, do everything in C#.
Why?
Because inter-language communication can get complicated and does not work both ways unless you get into very advanced stuff. Basic communication between a C# and a JS script can work, but you have to play with the folders a little. Anyway, you're making your life unnecessarily harder than it should, if you have a choice of course.
What you have to understand is that Unity compiles all your scripts in several passes. A script can only access other scripts :
from their own pass, if they are written in the same language
or from any previous pass, no matter the language it was written in.
With that in mind unity compiles certain specific folders in a specific order.
Here you're trying to access a JS from a C# script.
For this to work, your JS script needs to be compiled in an earlier pass than the C# one, so the C# script can find your script reference when it is compiled.
So in this particular case, you should put your C# script in the root or whatever custom (non-specific) folder you want (which are compiled in the regular pass) and leave the JS script in the Standard Assets folder (which is a specific folder, compiled in the preliminary pass).
Sir i cant thumbls up as my reputation isn't 15, but thanks alot for the explaination Now I know how to handle this type of error, Tons Of thanks :) have a blessed life.
Your answer
Follow this Question
Related Questions
Android Plugin Help 1 Answer
Android C# JoyStick Movement 0 Answers
How to check for null 2 Answers
[Solved] Boolean is true and flase every frame 3 Answers
Can i build and publish Android games on play store using Unity 5 personal free edition ? 2 Answers