Got a few issues with using Unity 2d scripting. I have sprite factory, and currently have 2 scripts. One is for running, one is for attack. Problems I am having are the following:
1) My character runs perfectly fine when moving right. When he runs in the left direction, the idle animation is always set to the right. So when he stops running left, it automatically moves the character back in the right direction when hes finished running
2) I have an attack script. This script works fine when scripted alone i.e. Attack.cs. However, when I activate my walk script aswell, the attack animation drops out completely. Do i need to merge the codes together?
3) Furthermore, I have 3 set of attacks, which I wish to program as the letter A. My character initiates the first attack fine, but as it is 3 sets of attack, the user would need to press the attack 3 times to initiate the 3 attacks. Should the character do 2 attacks, it should reset back to its initial attack.
Any recommendation with how to get profecient in C# would also be beneficial because i suck at Unity coding =(
My Code (Attack):
using UnityEngine;
using System.Collections;
using FactorySprite = SpriteFactory.Sprite;
public class Attack : MonoBehaviour {
// you forgot to set name of variable representing your sprite
private FactorySprite sprite;
// Use this for initialization
void Start () {
sprite = GetComponent<FactorySprite> (); // Edited
}
void Update ()
{
if(Input.GetKeyDown(KeyCode.A))
{
sprite.Play("Attack");
Vector3 pos = transform.position;
pos.x += Time.deltaTime * 1;
transform.position = pos;
}
}
}
My Code (Run)
using UnityEngine;
using System.Collections;
using FactorySprite = SpriteFactory.Sprite;
public class Walk : MonoBehaviour {
// you forgot to set name of variable representing your sprite
private FactorySprite sprite;
// Use this for initialization
void Start () {
sprite = GetComponent<FactorySprite> (); // Edited
}
// Update is called once per frame
void Update () {
if (Input.GetKey (KeyCode.RightArrow)) {
sprite.Play ("Walk"); // heh, remember C# is case sensitive :)
Vector3 pos = transform.position;
pos.x += Time.deltaTime * 6;
transform.position = pos;
} else if (Input.GetKey (KeyCode.LeftArrow)) {
sprite.Play ("Walk0"); // heh, remember C# is case sensitive :)
Vector3 pos = transform.position;
pos.x += Time.deltaTime * -6;
transform.position = pos;
} else {
sprite.Stop ();
}
}
}
I think that you should consider using state machine to manage your character position. In fact, it is a classic example of state machine usefulness. The book "Game Programming Patterns" has a great chapter about it; in fact, the very example that is used there is very close to the code that you're working on.
In the update function of the walk script you call sprite.stop() wich will stop the attack animation.
You could check if the active animation is Walk or Walk0 to not stop other animations.
http://docs.unity3d.com/Documentation/ScriptReference/Animation.IsPlaying.html
Solution could be something like this (untested):
Animation anim = gameObject.GetComponent<Animation>();
if (anim.IsPlaying("Walk") || anim.IsPlaying("Walk0")) {
sprite.Stop();
}
Or rather since you are using "Sprite Factory" as far as I can see from your code:
if (sprite.IsAnimationPlaying(1) || sprite.IsAnimationPlaying(2)) {
sprite.Stop();
}
Assuming in this case that the animationIndex for "Walk" is 1 and "Walk0" is 2.
You can read more about IsAnimationPlaying here: http://www.guavaman.com/projects/spritefactory/docs/pages/classes/Sprite-IsAnimationPlaying.html
Related
I'm totally newbie with Unity and C# and i try to do a 3D game.
I want to when i press "Qkey", the cube descends in height.
here is my code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ripcube : MonoBehaviour
{
// Start is called before the first frame update
bool isTeleported = false;
// Update is called once per frame
void Update()
{
if (Input.GetKey("a") && !isTeleported)
{
ripcube.transform.position = (-2, -2, -2) ;
}
}
}
And it gives me the error:
(19,13): error CS0120: An object reference is required for the non-static field, method, or property 'Component.transform'
I know than ripcube is my class, but what is my gameobject? i created my cube on the graphics interface..
Thanks for your help
You should go watch some basic videos on youtube on how unity gameobjects work but for now:
You can reference game objects from your code or find them as following:
public class ripcube: MonoBehaviour
{
GameObject myCubeObject;
float speed = 2f;
void Start()
{
myCubeObject = GameObject.Find("YourCubeNameInUnity");
}
void Update()
{
if(Input.GetKey(KeyCode.Q))
{
myCubeObject.transform.Translate(speed * Vector3.down * Time.deltaTime);
}
}
}
Thing you should notice here :
The GameObject is a Unity class that is the base for all the game objects in the scene,
you can find it by its name in the Hierarchy view.
After you find it you can access it in the Update() function and change its transform every frame.
Here I used Translate wich is an addition to the position every frame
you can also use myCubeObject.transform.position += speed * Vector3.down * Time.deltaTime
Be aware that im using a float speed variable that is the speed the cube will go in the desired direction (I used 2 for the value but it can be anything really).
The direction is specified by a vector (Vector3.down). You can change is as you please
Multiplying by Time.deltaTime makes the movement independant on FPS (Frames per second) wich is determined normally bt the machine the game is running on.
bro you can use
transform.position = new Vector3(-2, -2, -2);
instead of
transform.position = (-2, -2, -2) ;
and change
Input.GetKey("a")
to
Input.GetKey(KeyCode.Q)
I have just updated Unity to version 5.2.1 from 5.0.0 this morning and I experienced a few problems. After Unity translated the game to work for the new version, I tested the game. Everything worked fine, except that when I shot a bullet in my game, they would stick to the walls instead of bouncing off of them, but only at certain angles and distances. It was like the bullet was so fast that it skipped hitting the collider and got stuck inside of the collider. That would make a little bit of sense, but the weird part is that I have a C# script for slow motion in the game. Whenever I turn the slow motion on and then turn it off again, the problem with bullets sticking goes away. I cannot seem to figure out what is causing the problem and it definitely wasn't there before I updated the software. Can anyone help me out with this? Thanks. I'll post the bullet script and the slow motion script below. The bullet is instantiated inside the player script by the way.
Bullet Script:
using UnityEngine;
using System.Collections;
public class Bullet : MonoBehaviour {
public float bulletSpeed;
public float bulletOpacity;
public bool fadeOut;
Animator anim;
Rigidbody2D rigidbod;
SpriteRenderer spriterend;
public GameObject player;
public float aimRotation;
// Use this for initialization
void Start () {
anim = GetComponent<Animator> ();
rigidbod = GetComponent<Rigidbody2D> ();
spriterend = GetComponent<SpriteRenderer> ();
rigidbod.velocity = transform.right * bulletSpeed;
rigidbod.gravityScale = 0;
bulletOpacity = 1;
}
// Update is called once per frame
void Update () {
Destroy (gameObject, 3f);
spriterend.color = new Color (1f, 1f, 1f, bulletOpacity);
if (fadeOut == true)
bulletOpacity -= 0.03f;
if (bulletOpacity <= 0)
Destroy (gameObject);
aimRotation = player.GetComponent<Player> ().aimRotation;
}
void OnTriggerEnter2D (Collider2D bulletHit) {
/*if (bulletHit.gameObject.layer == LayerMask.NameToLayer ("vulnerableLayer")) {
}*/
rigidbod.gravityScale = 1;
rigidbod.drag = 1;
fadeOut = true;
}
}
Slow Motion Script:
using UnityEngine;
using System.Collections;
public class SlowMotion : MonoBehaviour {
public float currentLongevity = 0f;
public float slowAmount = 0.2f;
public float normalTime = 1f;
public float slowLongevity = 0.4f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown (1)) {
Time.fixedDeltaTime = 0.0f * Time.timeScale;
if (Time.timeScale == normalTime)
Time.timeScale = slowAmount;
}
if (Time.timeScale == slowAmount) {
currentLongevity += Time.deltaTime;
}
if (currentLongevity > slowLongevity) {
currentLongevity = 0;
Time.timeScale = normalTime;
}
}
}
Since you indicated that the 'weird' bullet behavior ceases after the SlowMotion script is run, I would suggest that the issue has to do with setting Time.fixedDeltaTime as you are doing in the Update() method of the SlowMotion script. This is also supported by your later comment that the 'weird' behavior no longer appears when you set the rigidBody2D's collision detection to continuous (the bullet's RigidBody2D I assume).
Continuous RididBody2D collision detection enables determining if contact occurred between updates, where as Discrete collision detection registers a collision during a physics update. In your SlowMotion script, the following line (in the Update() method) sets fixedDeltaTime to zero:
Time.fixedDeltaTime = 0.0f * Time.timeScale;
Since Time.fixedDeltaTime is the interval in seconds at which physics and other fixed frame rate updates are performed, there must be some minimum value at which the frame rate is realistically run, (0.0 cannot be an actual frame-rate update interval). When Time.fixedDeltaTime == 0.0, Unity may use a default minimum value or use this to indicate that frame updates run as often as possible, (though I have not tested this). Since the Bullet script calls Update() rather than FixedUpdate(), there is no guarantee that the actual interval between the frame updates is uniform. I suspect that when you run the SlowMotion script, and set Time.fixedDeltaTime to 0.0, Unity runs with the smallest possible frame update interval and following this, it does render the expected bullet behavior.
One way to test this would be to set your initial Time.fixedDeltaTime to 0.0 in the editor (and your collision detection behavior back to discrete for the bullet's RididBody2D).
To set Time Manager fixedDeltaTime in the editor: main menu -> Edit -> Project Settings -> Time
If you find a fixedDeltaTime that works, you can set this in the editor and retrieve the initial value in your SlowMotion script in the Awake() method to initialize the base fixedDeltaTime. I would not recommend using fixedDeltaTime == 0.0 since there is no indication in the documentation of a consistent behavior for a time interval of 0.0 and it may be bound more to the underlying hardware and could result in more unexpected behavior.
Hope this helps, cheers!
I've been working on this script for the past day. For some reason my character will not jump as long as it's animator is active. I've got into the animation (there is only one) and removed all references to the animation placing a position anywhere and still the issue presides.
I have discovered that I can make my player jump if I use Co-routine which I'm using. However, I'm still new to using them and I can't work out why my player won't fall to the ground once a force has been added to it. And my player only moves up when the button is clicked. Could someone please take a look at my script and tell me what I'm doing wrong?
public float jumpSpeed = 100.0f;
public float jumpHeight = 2.0f;
public AudioClip jumpSound;
private GameObject pos;
private bool moving;
private bool isJumping;
void Start()
{
}
// Update is called once per frame
void Update ()
{
if(Input.GetMouseButtonDown(0))// && !moving)
{
isJumping = true;
StartCoroutine(JumpPlayer(gameObject.transform.localPosition));
}
else
{
isJumping = false;
}
}
IEnumerator JumpPlayer(Vector3 startPos)
{
Vector3 jump = new Vector3(transform.localPosition.x, jumpHeight, transform.localPosition.z);
float t = 0f;
t += Time.deltaTime / jumpSpeed;
rigidbody.AddForce(Vector3.up * jumpSpeed);
//gameObject.transform.localPosition = Vector3.Lerp(startPos, jump, 0.5f);
//isJumping = false;
yield return null;
}
Firstly, your use of coroutine isn't doing anything in particular - because it only does yield return null at the end, it'll run in a single frame and then exit. You could make it a regular void function and you shouldn't see any change in behaviour.
Removing other redundant code and you have just this:
if(Input.GetMouseButtonDown(0))
{
rigidbody.AddForce(Vector3.up * jumpSpeed);
}
This force is added for only a single frame: the frame where the mouse button is pressed down (if you used Input.GetMouseButton instead, you'd see the force applied for multiple frames).
You say "my player only moves up when the button is clicked" but I'm not clear why that's a problem - perhaps you mean that the player should continue to move up for as long as the button is held, in which case you should refer to my previous paragraph.
The most obvious reasons for the player not falling again are related to the RigidBody component: do you have weight & drag set to suitable values? An easy way to test this would be to position your player some distance from the ground at the start of the scene, and ensure that they fall to the ground when you start the scene.
Another reason might be that you're using the default override of .AddForce in an Update cycle. The default behaviour of this method applies force during the FixedUpdate calls, and you might find that using ForceMode.Impulse or ForceMode.VelocityChange gives you the result you're looking for.
hi i was wondering if someone could help me fix practice code (i make practice codes before i make the real thing because its just how i roll) it is basically an object that requires the user to click on the screen in order for it to not touch the ground much like flappy bird however although i have applied gravity correctly to the sprite i cannot fix the velocity section (i coded is to every time the user clicks with his mouse or taps the space key the object will move up like flappy bird)
using UnityEngine;
using System.Collections;
public class BirdMovment : MonoBehaviour {
Vector3 Velocity = Vector3.zero;
public Vector3 gravity;
public Vector3 flapVelocity;
public float maxSpeed = 5f;
bool didFlap = false;
// Use this for initialization
void Start () {
}
void update (){
if (Input.GetKeyDown (KeyCode.Mouse0))
{
didFlap = true;
}
}
// Update is called once per frame
void FixedUpdate () {
Velocity += gravity* Time.deltaTime;
if (didFlap) {
didFlap = false;
Velocity += flapVelocity;
}
Velocity = Vector3.ClampMagnitude (Velocity, maxSpeed);
transform.position += Velocity * Time.deltaTime;
}
}
can you please fix the error as every time i set the velocity in unity for the sprite ad run the program the sprite just keeps on falling and no matter how much i click or tap the space key the sprite does not stop falling even if i increase the velocity
First of all, the correct Update function is with a capital U, so Update() instead of update(). Then, since you're not doing anything with physics, you can do everything in Update and not use FixedUpdate at all. So you can remove the didFlap variable and add to Velocity directly inside the if (Input.GetKeyDown ...) block. Furthermore, regarding gravity, you're multiplying it twice with Time.deltaTimethere, so remove the first one. That should get you started.
I'm writing a 2D game and I'm trying to get moving platforms to work. After doing some previous investigation, I have it ALMOST working. The idea is to have 2 platform objects with colliders: 1 a visible object, the other an invisible object with isTrigger set (since the player would just go through a trigger). The code for the Moving Platform child (the trigger one) is set here.
using UnityEngine;
using System.Collections;
public class MovingPlatformChild : MonoBehaviour
{
public string parentPlatform = "";
void Start ()
{
transform.parent = GameObject.Find(parentPlatform).transform;
}
// Update is called once per frame
void Update ()
{
}
void OnTriggerEnter(Collider playerObject)
{
Debug.Log ("enter moving platform");
if(playerObject.gameObject.name.Contains("Player"))
{
playerObject.transform.parent = gameObject.transform;
}
}
int i = 0;
void OnTriggerStay(Collider playerObject)
{
Debug.Log ("stay" + i++);
if(playerObject.transform.position.y >= transform.position.y)
{
playerObject.transform.parent = gameObject.transform;
}
else
{
playerObject.transform.parent=null;
}
}
void OnTriggerExit(Collider playerObject)
{
Debug.Log ("EXIT");
if(playerObject.gameObject.name.Contains("Player"))
{
playerObject.transform.parent=null;
}
}
}
The Start() function just makes it a child of the visible platform. This can probably be done right in the Unity editor as well, instead of through code.
The OnTriggerEnter function adds the player object as a child of the trigger platform object, which is a child of the visible platform. So they should all move together.
The OnTriggerStay is an attempt to verify that this remains true only while the player is on the top of the platform. While the player is within the trigger, if the player is on top of the platform, then it remains attached. Otherwise, it's not. This is so that nothing happens on the bottom end.
The OnTriggerExit function just removes the player object as a child when it exits the trigger.
This is somewhat working (but we know somewhat isn't good enough). It works sometimes, but the player will be very jittery. Also, on the way down while standing atop the platform, the TriggerStay function doesn't appear to be called (implying the player is no longer within the trigger). This is observed through my Debug "stay" statement. Finally, sometimes the player will also fall straight through the platform.
What in this code would allow the player to fall through the platform, or be so jittery on the way up? Am I missing something crucial? If you need any more code, please let me know.
Below is the code for the movement of the non-trigger platform (the parent of the trigger platform and in an identical position). I will also share the Player's Update function after that.
void Start ()
{
origY = transform.position.y;
useSpeed = -directionSpeed;
}
// Update is called once per frame
void Update ()
{
if(origY - transform.position.y > distance)
{
useSpeed = directionSpeed; //flip direction
}
else if(origY - transform.position.y < -distance)
{
useSpeed = -directionSpeed; //flip direction
}
transform.Translate(0,useSpeed*Time.deltaTime,0);
}
And now the player code:
void Update()
{
CharacterController controller = GetComponent<CharacterController>();
float rotation = Input.GetAxis("Horizontal");
if(controller.isGrounded)
{
moveDirection.Set(rotation, 0, 0); //moveDirection = new Vector3(rotation, 0, 0);
moveDirection = transform.TransformDirection(moveDirection);
//running code
if(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) //check if shift is held
{ running = true; }
else
{ running = false; }
moveDirection *= running ? runningSpeed : walkingSpeed; //set speed
//jump code
if(Input.GetButtonDown("Jump"))
{
//moveDirection.y = jumpHeight;
jump ();
}
}
moveDirection.y -= gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
}
EDIT: I've added the specifications for the platforms and player in this imgur album:
http://imgur.com/a/IxgyS
This largely depends on the height of your trigger box, but it's worth looking into. Within your TriggerStay, you've got an IF statement concerning the player y coordinates. If the trigger box is fairly large and the platform's speed fast enough, on the way up and between update ticks the player Y coords could momentarily be smaller than the trigger Y coords. This would lead to him losing the parentage, only to regain it a few ticks later. This might be the cause of the 'jittering'.
The problem I was having included
The moving platform was written using Translate. I rewrote it using a rigidbody and the rigidbody.Move function. This didn't immediately help, but...
I realized the CharacterMotor script (Unity provides this) that I had attached to the player included moving platform support. I set the MovementTransfer value to PermaLocked, and also unchecked the "Use FixedUpdate" box on the script, and it now works 99% of the time. I've had one time where I did a particular behaviour and slipped through, but I can't recreate it.
Hope this helps anyone who might be looking for an answer!