Help Needed with Unity Tutorial

edited in Questions and Answers
Hi Guys

I've started working through a book that teaches the basics of Unity, but have run into a piece of code that does not seem to work. I have copied it word for word from the book, but no luck. I was hoping someone could spot my mistake (hopefully not something totally embarrassing). It is a movement controller, javascript script that I am attaching to a GameObject with a CharacterController.

var rollSpeed = 6.0;
var fastRollSpeed=2.0;
var JumpSpeed=8.0;
var gravity = 20.0;
var rotateSpeed=4.0;
var duckSpeed=0.5;

private var moveDirection=Vector3.zero;
private var grounded:boolean=false;
private var moveHorz=0.0;
private var normalHeight=2.0;
private var duckHeight=1.0;
private var rotateDirection=Vector3.zero;

var isControllable: boolean = true;

var controller: CharacterController;
controller=GetComponent(CharacterController);


function FixedUpdate(){
if(!isControllable)
Input.ResetInputAxes();
else{

if(grounded){ 
moveDirection = new Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxi s("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= rollSpeed;
controller.height = normalHeight; 
controller.center.y = controller.height/2;

moveHorz = Input.GetAxis("Horizontal"); 
if(moveHorz > 0) // positive values are right negative are left 0 is forward and back
rotateDirection = new Vector3(0,1,0); //turn right
else if(moveHorz < 0)
rotateDirection = new Vector3(0,-1,0); //turn left
else
rotateDirection = new Vector3(0,0,0);


if(Input.GetButton ("Jump")) {
moveDirection.y = JumpSpeed; // y position is changed to jumpspeed variable
}
if(Input.GetButton("Boost")){// boost speed is current speed X boost variable
moveDirection *= fastRollSpeed;
}
if(Input.GetButton("Duck")){
controller.height=duckHeight;
controller.center.y = controller.height/2 + .25;
moveDirection *= duckSpeed;}

moveDirection.y -= gravity * Time.deltaTime;// multiplying by time delta is doing stuff by the second

// Getting the controller to move and stay with character
var flags = controller.Move(moveDirection * Time.deltaTime);
controller.transform.Rotate(rotateDirection * Time.deltaTime, rotateSpeed);
grounded= ((flags & CollisionFlags.CollidedBelow)!=0);


}// end of if grounded -----------------------------------------------------------


}}

Comments

  • does not seem to work
    Does it not compile? Is there an error? Does it not do what you expect?

    Some context would be nice. :)
  • edited
    Sorry about that - Does not compile

  • edited
    You have an extra space at line 27 (at Input.GetAxis):
    moveDirection = new Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxi s("Vertical"));


    Though I'm not sure if that came from pasting the code here. Could it be that?
  • no space - comes from posting here
  • If it doesn't compile, what error does it give you?
  • @Elyardine - I will post the exact error message tonight, as I am at work at the moment. Sorry for being so unprepared. Just saved the script onto a flash drive quickly this morning before leaving home in the hopes that someone here would be able to assist. Thanks for your showing such patience.
  • edited
    @Manikin - Man I am embarrased to admit this, but that space was the problem. That and I deleted the #pragma strict line (what does that mean/do anyway - is it like C#'s using statements?) - Is there a way to get the build in Editor to highlight mistakes like this? You know like the red squiggly line you get in Visual Studio or an error list that you can see somewhere in the Editor?

    @Elyaradine - Thanks again for being willing to assist. Didn't see the the error list in the console last night when I tried to compile for the very first time in Unity. Learning new software can be a bitch, especially if you make noob errors like this, but then again how else does one learn. Thanks again :)
  • Heh, glad it's sorted. I didn't do anything. :P
  • edited
    @FanieG a "#pragma" is what you call a pre-compiler directive and it gives the compiler certain instructions when dealing with your code. "#pragma strict" disables dynamic typing so you don't have ambiguity with variable types, also I think it's compulsory when deploying to ios? Dynamic typing is declaring a variable without a type and then letting unity figure out what that type is (which eats up more resources than static typing)

    e.g

    var Message = "Hello"; // Dynamically typed
    var Message : String = "Hello"; // Statically typed


    Although I'm pretty sure you can get away with some basic variable typing even with the strict pragma. Something like:
    #pragma strict
    var MagicVariable;
    
    function Start() {
        MagicVariable = 1+1;
        MagicVariable = "two";
    }


    Should run without giving a compiler error. Casting unity related variables like gameobjects and transforms will throw errors
  • @FanieG Hehe no worries, mistakes like that can be a mission to spot! I didn't know what the #pragma strict was either, but now I get it thanks to @Stray_Train. I use C# so haven't used it in my code yet.

    Re: error highlighting - I'm not sure if there's a way to get that. I'm sure some of the guys using Visual Studio here will know, but I'm still using MonoDevelop (bundled with Unity), which is probably a bad idea because it does drive me nuts sometimes. MD highlights certain errors but not others. Otherwise, I just check what the console says. You can normally double click the error in the console and it'll take you to the offending line in MonoDevelop.
    Anyway, hope it helps!
  • @Stray_Train - Thanks so much for taking the time to explain that. It really helps and is much appreciated.

    @Manikin - I found the error list under MonoDevelop's view options, but for some reason errors listed in the Unity console line do not appear as errors in the editor? Anyway, I am also more of a C# guy, but the book i'm working through has only Javascript examples. I thought I would work through the book and then translate all of the scripts into C# afterwards. Should be good practice and i'm getting a bit of Javascript experience at the same time.
  • edited
    Hi Guys. I have a new problem. I'm working on a 2d space invaders game and I have a mothership that drops bombs (Instantiates at the motherships position) when certain criteria is met. The bombs fall straight down towards the bottom of the screen where the player is (velocity.y = negative speed). The player has a capsule collider which has been ticked as a IsTrigger. When the bombs enter the trigger i want the player to be destroyed. Both the bombs and the player has a rigidbody component attached to it. My code is very simple :

    void OnTriggerEnter()
    	{
    		Destroy(gameObject);
    	}


    but for some reason the bombs are just falling straight trought the player and not firing the trigger. What can be the problem? Any help will be appreciated. Also, if other items (enemies) enter the trigger the player does get destroyed?
  • That OnTriggerEnter function needs the other collider's collider as an argument, so it should look something like this:

    void OnTriggerEnter(Collider otherCollider)
    {
    	Destroy (gameObject);
    }


    If you want to check for different kinds of objects (eg. enemy hitting player, or bullet hitting player), one of the most common practices - as far as I'm aware - is to assign your enemy prefabs an "Enemy" tag and your bombs a "Bullet" tag, or some other similar naming. Then you can check for the type in your OnTriggerEnter. So for example:

    void OnTriggerEnter(Collider otherCollider)
    {
    	if (otherCollider.gameObject.tag == "Bullet")
    	{
    		Destroy (gameObject); //kills the player
    	}
    	else if (otherCollider.gameObject.tag == "Enemy")
    	{
    		Destroy (otherCollider.gameObject); //kills the enemy (otherCollider is enemy's collider)
    	}
    }


    Hope that helps!
  • @Manikin - Thanks for stepping up to help again. Found that the problem was that the project physics settings was set to not have the bullet layer and the player layer interact with each other (block was unticked), but thanks for the advice above. I did not know that you could pass an argument to the OnTriggerEnter method. Just for clarity if my item is called bullet - do i reference it as (Collider bullet) or (Collider bullet.SphereCollider). Sorry if this question seems retarted. I'm still learning.
  • No problem @FanieG, happy to help. And your questions aren't stupid at all - these are all valid when learning stuff :)

    If I'm understanding your question correctly (and I only know it in terms of C#), you could reference the collider with
    bullet.collider
    just as you would get any other component attached to the bullet, eg.
    Transform t = bullet.transform; 
    Material m = bullet.renderer.material;

    With the collider example, it's just a shortcut of (in C#)
    bullet.GetComponent<SphereCollider>()
  • @Manikin - Legend!!! This is going to help me so much.
    Thanked by 1Manikin
  • @Manikin said:
    Material m = bullet.renderer.material;
    Never do this! That's a one way trip to having an extra material in your game that nothing will clean up when you're done.
  • Ah ok, didn't realize that. You can apply changes to the material like
    bullet.renderer.material.color = bulletColor
    without it adding an extra one to the game, right?
  • Run it and see. :) You'll end up with a material with the "(Instance)" suffix to it, and your number of draw calls will increment.

    I wouldn't say you should never do it though -- there are some cases where I have a few instances of the same material happening simultaneously (usually for fx, where I might animate a material property, but the fx object is destroyed after a few frames anyway)... but for the most part you'd want to use renderer.sharedMaterial instead of renderer.material.
    Thanked by 1Gazza_N
  • edited
    So let me get this straight (since I'm learning Unity too): referencing the renderer.material has Unity create a separate cloned instance of the material for alteration, then just leaves it hanging in memory even when unlinked to a gameObject, but referencing the renderer.sharedMaterial alters the core material definition, which ripples across all other linked objects as you'd expect?

    Is there any way to explicitly kill the material in that case, since the GC clearly doesn't do it?
  • edited
    @Gazza_N: Yes, that's pretty much it. Basically, you have to keep a pointer to the material you're messing with in script and explicitly destroy it when the object that "owns" it gets destroyed. The biggest thing to look out for is doing multiple renderer.material references (and thus getting multiple, unreferenced clones), make your changes via the pointer you've stored.
    Thanked by 1Gazza_N
  • Righto. So the issue's that the GC ignores materials (assuming that you may want to reference them elsewhere), and you need to be explicit in their creation and destruction to ensure that things don't get all leaky. Excellent to know! Thanks! :D
  • Yes, that's pretty much it. Basically, you have to keep a pointer to the material you're messing with in script and explicitly destroy it when the object that "owns" it gets destroyed. The biggest thing to look out for is doing multiple renderer.material references (and thus getting multiple, unreferenced clones), make your changes via the pointer you've stored.
    Damn, that's pretty hardcore, I had no idea that happened. I was looking around for more on this and this answer has some more detail: http://answers.unity3d.com/questions/192561/renderermaterials-leaking-materials.html - they don't get GC'd because they are technically assets.

    They will get cleaned up when the scene changes, or with call to Resources.UnloadUnusedAssets.
    Thanked by 1Gazza_N
  • Thanks to all for the advice
  • Crazyness, thanks guys, I had no idea about all that.
  • Okay MGSA guru's another noob question that I need help with. I'm working on my first FPS project. I'm using the standard FPS contoller prefab that comes package with Unity. I have added a reticle at the centre of the screen using a 2nd camera. But when I build and run my project the normal mouse pointer is still present on the screen. Which is confusing as the reticle is the actual indicator of where i am looking. Is there a way to remove the mouse pointer (arrow) from my scene and only have the reticle present? As always any help would be greatly appreciated.
  • Short answer :
    Screen.showCursor = false


    Long answer:
    Google and reference documents. Unity has a really well documented API. You can find a lot of useful stuff there.
    http://docs.unity3d.com/Documentation/ScriptReference/Screen-showCursor.html
  • @Rigormortis - thanks for both answers. Tried googling the answer last night, but couldn't find the word "Cursor" *facepalm*. Was looking for arrow, pointer etc. (enter Homer Simpson - Dohh!! here). Thanks for assisting.
  • Hehe, no problem. :)
  • Okay, so I wrote a method for Screen.showCursor = false and I am calling the method in the Start() of each level in my game (attached it to my UI camera). However, the cursor is still visible when the first level loads. It then disappears as soon as I click a mouse button. Is there a go around for this or a better place to call the method. Just a "keyword" to google would be great. Don't want to waste anybody's time with answers for problems I should probably solve myself. Still learning guys. Thanks in advance for any help
  • @FanieG...hmmm, I didn't mean to say you shouldn't ask questions with my previous post about google-ing. I was just suggesting that it might me good to read around the thing your actually trying to do as well...sort of a tangential learning effect. I do it that way, not sure if it's useful for everyone though.

    Anyway, can you maybe post the method and call you make? It sounds like it should be working. You can maybe try to put it in the Awake() method of your camera. Are you running the game in the editor? If you are try to make a build and see if it still happens there.
  • @Rigormortis - Yeah, I think the problem was because it was in the Editor. If I build the game and run it is fine. Weird. I will try it in the Awake() and see what that does in the Editor. And no stress about the google hint. I did not take it up as a negative. I just know from visiting other coding forums that some members can get quite upset if one asks a question which can easily be found by googling. Always kind of frown on such behaviour as i'm one of those people that believe "there is no such thing as a dumb question". That being said I also believe in self-study for personal growth. I am so grateful for this community where you rarely see people turning "nasty" or looking down on new learners. The pool of knowledge here is AMAZING.

    Thanks again for helping.
  • The main reason I think that you should get into a habit of googling isn't because there are things like dumb questions...it's just that there is usually someone that has asked the same questions before so it's faster to get the answer that way than waiting for someone to respond on a forum.

    I wouldn't worry about putting it in the awake function thought. If it's because it's in the editor is probably because the game window in the editor doesn't have focus when you run it, and as soon as you click it gains focus and stops rendering the cursor. It should be fine as is.
  • in the words of the Beatles : "Help!"

    I have a script that allows my FPS player to pick up a cube and hold it at a distance before the main camera, and it moves with the player (parented to camera). To get the cube to rotate with the player it's isKinematic is switched to True. This works fine. However the cube now ignores physics and is able to move through walls (stretched out cubes) while being held. If I add a Rigidbody to the walls, the held cube no longer moves through them, but then the walls get pushed around when the cube bumps into them. I've tried switching of the gravity on the wall's rigidbody and making them really heavy, but that had some comical effects. I tried moving the wall down into the plane, but that had even more hilarious effects. I tried google, but was unsuccesfull. If anyone can help out a noob again it would be much appreciated.

    Here's the script i'm using:

    using UnityEngine;
    using System.Collections;
    
    public class PickupDrop : MonoBehaviour {
    
    	public float pickupDistance = 2.0f;
    	public float holdDistance = 2.0f;
    	private bool isHoldingSomething = false;
    	private GameObject heldObject;
    	public LayerMask pickupMask;
    	
    	// Use this for initialization
    	void Start () {
    	
    	}
    	
    	// Update is called once per frame
    	void Update () 
    	{
    		RaycastHit hitInfo;
    		
    		if(!isHoldingSomething)
    		{
    			if(Physics.Raycast(transform.position,transform.forward,out hitInfo,pickupDistance,pickupMask))
    			{
    				if(Input.GetMouseButtonDown(1))
    				{
    						hitInfo.collider.transform.parent = transform.parent;
    						hitInfo.collider.rigidbody.isKinematic = true;
    						Vector3 newPosition = transform.position;
    						newPosition += transform.forward * holdDistance;
    						hitInfo.transform.position = newPosition;
    						heldObject = hitInfo.collider.gameObject;
    						isHoldingSomething = true;	
    				}
    			}
    		}
    		else 
    		{
    				Vector3 newPosition = transform.position;
    				newPosition += transform.forward * holdDistance;
    				heldObject.transform.position = newPosition;
    				if(Input.GetMouseButtonDown(1))
    				{
    					heldObject.rigidbody.isKinematic = false;
    					heldObject.transform.parent = null;
    					heldObject = null;
    					isHoldingSomething = false;
    				}			
    		}
    	}
    }
  • edited
    A quick fix(meaning without understanding everything you want to do) could be to lock the position on the wall's rigidbody. You can edit the constraints on a rigidbody so that physics won't move it in certain ways. Select the wall object and expand the rigidbody's constraints options and just tick everything.

    Edit: This would at least stop the walls from moving, but it might behave oddly.
  • edited
    @Rigormortis - thanks. I tried that, but then i'm back to the original problem where the cube simply moves through wall. I basically need a way for the wall to keep it's rigidbody, but not react to force (If that's even possible), or maybe there is an easier solution I did not think of/know of?

    or I need a way that the wall's collider will still collide with a kinematic object but not be moved by it
  • edited
    [quote = Unity Reference]If isKinematic is enabled, Forces, collisions or joints will not affect the rigidbody anymore. The rigidbody will be under full control of animation or script control by changing transform.position.[/quote]

    So by making your carried cube's isKinematic property true you are essentially telling it to ignore the collisions it has with the walls. Because the rigidbody on the wall's isKinematic property is false, it is affected by the collision. If you lock the position and rotation it shouldn't move though. If you want Unity to handle the collisions you can't turn on isKinematic.

    What do you want the behaviour to be on the block/object being carried when it hits a wall? Should it stop against the wall as well as preventing the player from moving in that direction? What is the behaviour you are looking for?
  • @Rigormortis -
    Should it stop against the wall as well as preventing the player from moving in that direction?
    That is exactly what I need it to do. Like I said, while the cube is picked up Unity is ignoring the physics due to the isKinematic being true (which i needed in order for the cube to move with the player). So while carrying the cube, my player can't move through walls (which is correct), but the cube can (which is wrong). Is there a way around this while isKinematic is true?

    I'm working on a physics type game, and the cubes are used to trigger events as well as for stacking in order to reach higher areas. So it is frustrating when you try to stack the cubes next to a wall if they are able to go through the wall or alternatively move the wall. It is really a barrier to my game being fun, so I really hope I can fix this.
  • I unfortunately do not know an easy way to do that. If you make the object kinematic you would have to handle the collision some other way. As far as I know the event still gets triggered so you can use OnCollisionEnter() and other methods like it, but you'd have to implement the code to tell it what happens on that collision.
    FanieG said:
    which i needed in order for the cube to move with the player
    What happened when you didn't make it kinematic?
  • @Rigormortis:
    What happened when you didn't make it kinematic?
    It would kinda drag/roll around when the player turned. Did not want to rotate with the player and it did not lift off the ground. Physics were basically all screwy. I'll google to see how other scripts handle carrying items around in first person, try them out and see if they have a similar issue with items moving through walls. Wonder how the guys from Visceral Clean-up Duty handeled this? That game is all about picking stuff up
  • Hi Guys. Need help again. I want to add 2 animations (idle and shoot) to my gun in my FPS game. I have the idle playing automatically (ping pong) then I play the shoot animation on Fire (mouse click). I want the game to then wait until that animation has stopped playing and then return to the idle animation. So I tried using a coroutine (very new to this) to go back to the first animation but no luck. So my idle plays at the start, the shoot animation plays when i click shoot, but then does not return to the idle. Here is my script:

    using UnityEngine;
    using System.Collections;
    
    public class PlayGunAnimations : MonoBehaviour {
    
    	public string fireButton = "Fire1";
    	
    	// Use this for initialization
    	void Start () {
    	
    	}
    	
    	// Update is called once per frame
    	void Update () 
    	{
    		if(Input.GetButtonDown(fireButton))
    		{
    			animation.Stop();
    			animation.Play("gunFireAnimation");
    		}
    		else
    		{
    			gunIdlePlayAgain();
    		}
    	}
    	
    	IEnumerator gunIdlePlayAgain()
    	{
    		yield return new WaitForSeconds(2);
    		animation.Play("gunIdleAnimation");
    	}
    }


    please help if you can
  • I am not sure if this will work, haven't used it yet :P but try:

    if(Input.GetButtonDown(fireButton) && animation.Play("gunFireAnimation") == false)
    		{
    			animation.Stop();
    			animation.Play("gunFireAnimation");
    		}


    Else I think it might be because you call the gunFireAnimation first in the code it is preceding the other animation. So then just use this at the bottom animation.Play() :

    IEnumerator gunIdlePlayAgain()
    	{
    		yield return new WaitForSeconds(2);
    		animation.Play("gunIdleAnimation",PlayMode.StopAll);
    	}


    If I'm wrong then cool story :P I'm still trying to get a 2D game up haha
  • @RickyGC - thanks for the suggestion. Got it fixed by useing Crossfade instead of Play. See below

    using UnityEngine;
    using System.Collections;
    
    public class PlayGunAnimations : MonoBehaviour {
    
    	public string fireButton = "Fire1";
    	
    	// Use this for initialization
    	void Start () {
    	
    	}
    	
    	// Update is called once per frame
    	void Update () 
    	{
    		if(Input.GetButtonDown(fireButton))
    		{
    			animation.CrossFade("gunFireAnimation");
    		}
    		else if(Input.GetButtonUp(fireButton))
    		{
    			animation.CrossFade("gunIdleAnimation");
    		}
    	}
    }
  • Hi Guys. New issue that I can't seem to get right. I have game objects with a tag "Drone", which has 3 scripts attached to it, but which is not enabled as default. I have created a trigger object that sends a message (activateObject) to all game objects with the tag "Drone" when activated. I then have a method (activateObject) that should enable the 3 scripts on the gameObject when it receives the message. this is my script for the method:

    void objectActivate()
    	{
    		gameObject.GetComponent<FastZombieAI>().enabled = true;
    		gameObject.GetComponent<FastZombieBite>().enabled = true;
    		gameObject.GetComponent<CurrentNode>().enabled = true;
    	}


    This is not working. The trigger fires and the gameobjects receives the message, but the scripts are not enabled. Any help with this would really be appreciated.
  • edited
    How I usually do it: (written from memory, so could be wrong)
    FastZombieAI fastZombieAI = gameObject.GetComponent(typeof(FastZombieAI)) as FastZombieAI;
    fastZombieAI.enabled = true;


    Edit: Make sure the scripts you are trying to enable are on the same gameObject as the script with the method. otherwise you will need a reference to where the scripts are located.
  • @Pixel_Reaper - thanks. This is kinda embarrasing, but it seems my way also worked as long as I remember to re-enable the box collider on my trigger object after I removed it to test something...*face meet palm*. Your code does seem cleaner though.
  • @FanieG cool glad you could sort it out :) well my way is longer, but I like the control it gives me over the instance of that script, so I can feed stuff into it, like variables or call public methods directly like that without using .SendMessage()
  • @Pixel_Reaper - that does make more sense. Glad to say that I now have my comp E game running at a solid 60+ FPS (no build posted yet). Want to also try out some other optimization options i've been reading about. Thanks for the help.
Sign In or Register to comment.