I have a bool variable (isGrounded) from my player's movement control script that I want to access in another GameObject.
BallController.cs
public class BallController : MonoBehaviour {
Transform myTrans;
Rigidbody2D myBody;
public bool isGrounded = true;
public bool release = false;
}
GravityPull.cs
public class GravityPull : MonoBehaviour {
public GameObject target;
public int moveSpeed;
public int maxdistance;
private float distance;
void Start ()
{
target= (GameObject.Find("Ball (1)"));
}
void Update ()
{
distance = Vector2.Distance (target.transform.position, transform.position);
if (distance < maxdistance && target.isGrounded)
{
target.transform.position = Vector2.MoveTowards(target.transform.position, transform.position, moveSpeed * Time.deltaTime / distance);
}
}
}
If I make my target a GameObject than I can find it using .find. But if I do this I can't access the bool. If I make my target a BallController then I can access the bool, but I can't use .find to find the class. I also can't cast the GameObject as a BallController. Can someone tell me what I'm doing wrong here?
target.getComponent<BallController>().isGrounded
this should be sufficient.
Related
I want to create a 2d game but when I want the player to avoid being able to jump infinitely in the air by recovering his position I get an error.
My error :
Transform' does not contain a definition for 'postion' and no
accessible extension method 'postion' accepting a first argument of
type 'Transform' could be found
My code :
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float moveSpeed;
public float jumpForce;
public Rigidbody2D rb;
private Vector3 velocity = Vector3.zero;
public bool isJumping;
public bool isGrounded;
public Transform groundCheckLeft;
public Transform groundCheckRight;
// Update is called once per frame
void FixedUpdate()
{
isGrounded = Physics2D.OverlapArea(groundCheckLeft.Position, groundCheckRight.Position);
float horizontalMovement = Input.GetAxis("Horizontal") * moveSpeed * Time.deltaTime;
if (Input.GetButtonDown("Jump") && isGrounded)
{
isJumping = true;
}
MovePlayer(horizontalMovement);
}
void MovePlayer(float _horizontalMovement)
{
Vector3 targetVelocity = new Vector2(_horizontalMovement, rb.velocity.y);
rb.velocity = Vector3.SmoothDamp(rb.velocity, targetVelocity, ref velocity, .05F);
if(isJumping == true)
{
rb.AddForce(new Vector2(0f, jumpForce));
isJumping = false;
}
}
}
It's transform.position not postion
Edit: Yep, just like Snir Ego said.
the solution should be simple, you wrote groundCheckLeft.Postion instead of groundCheckLeft.position
I am trying to make the Enemy Play an animation on trigger collision but I am getting the error message below.
Assets\Scripts\you.cs(49,18): error CS1501: No overload for method 'Play' takes 3 arguments
My code:
using UnityEngine;
using System.Collections;
public class you : MonoBehaviour
{
public const float InitialSpeed = 0.5f;
public bool isDead = false;
public float upForce = 100f;
public LayerMask ground;
private Rigidbody2D rb2d;
public float speed = InitialSpeed;
public bool isgrounded = false;
public float checkradius = 0.5f;
public GameObject groundcheck;
public float translation;
public Animation anim;
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
anim = GetComponent<Animation>();
}
void Update()
{
transform.Translate(translation, 0, 0);
isgrounded = Physics2D.OverlapCircle(transform.position, checkradius, ground);
translation = Input.GetAxis("Horizontal") * InitialSpeed;
if (isDead == false)
{
if (Input.GetKeyDown("space"))
{
rb2d.velocity = Vector2.zero;
rb2d.AddForce(new Vector2(0, upForce));
}
}
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.tag == "Enemy")
{
anim.Play("Enemydie", 0, 0f);
Debug.Log(other.gameObject.name);
Destroy(other.gameObject, 0.1f);
}
}
}
Maybe someone could help I've looked through other posts but can't seem to find one that fixes my problem.
Animation.Play only takes 2 arguments, 1 of which is optional.
public bool Play(PlayMode mode = PlayMode.StopSameLayer);
public bool Play(string animation, PlayMode mode = PlayMode.StopSameLayer);
If you are indeed using an Animation component and not an Animator which takes 3 arguments, then you can update to:
anim.Play("Enemydie");
I assume you are indeed using an Animation component as you would be getting a null ref exception when trying to call Play()
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class SpinableObject
{
[SerializeField]
private Transform t;
[SerializeField]
private float rotationSpeed;
[SerializeField]
private float minSpeed;
[SerializeField]
private float maxSpeed;
[SerializeField]
private float speedRate;
private bool slowDown;
public void Rotate()
{
if (rotationSpeed > maxSpeed)
slowDown = true;
else if (rotationSpeed < minSpeed)
slowDown = false;
rotationSpeed = (slowDown) ? rotationSpeed - 0.1f : rotationSpeed + 0.1f;
t.Rotate(Vector3.forward, Time.deltaTime * rotationSpeed);
}
}
public class SpinObject : MonoBehaviour
{
private bool slowDown = false;
private GameObject[] allPropellers;
public bool rotateAll = false;
public float rotationSpeed;
public float slowdownMax;
public float slowdownMin;
public SpinableObject[] objectsToRotate;
// Use this for initialization
void Start()
{
allPropellers = GameObject.FindGameObjectsWithTag("Propeller");
}
// Update is called once per frame
void Update()
{
if (rotateAll == false)
{
for (int i = 0; i < objectsToRotate.Length; i++)
{
objectsToRotate[i].Rotate();
}
}
else
{
objectsToRotate = new SpinableObject[allPropellers.Length];
for (int i = 0; i < allPropellers.Length; i++)
{
objectsToRotate[i].Rotate();
}
}
}
}
In the else in this part I want that all the objects will rotate with the global variables settings. And if the rotateAll is false each one will rotate with their own options settings.
objectsToRotate = new SpinableObject[allPropellers.Length];
for (int i = 0; i < allPropellers.Length; i++)
{
objectsToRotate[i].Rotate();
}
But here I'm only make instance for more places in the objectsToRotate they are all null. And I'm not sure using objectsToRotate is good to rotate them all at once.
Update: This is what i tried now:
I changed the SpinableObject script to:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class SpinableObject
{
public Transform t;
public float rotationSpeed;
public float minSpeed;
public float maxSpeed;
public float speedRate;
public bool slowDown;
}
public class SpinObject : MonoBehaviour
{
public SpinableObject[] objectsToRotate;
private Rotate _rotate;
private int index = 0;
private bool rotateAll;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
var _objecttorotate = objectsToRotate[index];
_rotate.t = _objecttorotate.t;
_rotate.rotationSpeed = _objecttorotate.rotationSpeed;
_rotate.minSpeed = _objecttorotate.minSpeed;
_rotate.maxSpeed = _objecttorotate.maxSpeed;
_rotate.speedRate = _objecttorotate.speedRate;
_rotate.slowDown = _objecttorotate.slowDown;
index++;
}
}
And created a new script name Rotate:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rotate : MonoBehaviour
{
public Transform t;
public float rotationSpeed;
public float minSpeed;
public float maxSpeed;
public float speedRate;
public bool slowDown;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
RotateObject();
}
public void RotateObject()
{
if (rotationSpeed > maxSpeed)
slowDown = true;
else if (rotationSpeed < minSpeed)
slowDown = false;
rotationSpeed = (slowDown) ? rotationSpeed - 0.1f : rotationSpeed + 0.1f;
t.Rotate(Vector3.forward, Time.deltaTime * rotationSpeed);
}
}
The idea is to feed the variables and settings in the script Rotate from the script SpinableObject.
But i messed it up it's not working and give me some null exception.
Is it a good way ? And how can i fix the scripts to work with each other so the SpinableObject will feed the Rotate with data.
This is how I would approach your problem.
I will define a global variable to determine if objects are rotating all at the same time or independently.
Then I will create a script called rotation and I will add it to each GameObject in your scene which will rotate.
In this script I will just include the
...
Update()
{
if (rotateAll == false)
{
Rotate(allProperties)
}else{
Rotate(particularProperties)
}
}
//Here you can implement the Rotate function passing the attributes you consider to make the rotation different for each case
...
And about global variables in Unity. One possible approach is to define a class like:
public static class GlobalVariables{
public static boolean rotationType;
}
Then you can access and modigy this variable from another script like:
GlobalVariables.rotationType = true;
if(GlobalVariables.rotationType){
...
}
After Edit:
I canĀ“t really tell what you are doing wrong, but if there is a null exception it may be you are not calling properly from the script the gameObjects you want to rotate. It could be you are not linking them correctly in the inspector. If you have declare
public SpinableObject[] objectsToRotate;
It is possible you forgot to drag and drop in the inspector the GamesObjets into the array to populate it. But I can't be sure if the problem is just that.
New to making games in Unity and I've tried to use every way possible to find the answer for this.
How would I add a touch screen function to this C# code in unity to make the player move left and right?
My code
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour
{
private Rigidbody2D rigi;
private Animator anim;
[HideInInspector]
public bool isFacingRight = true;
public float maxSpeed = 7.0f;
public Transform groundCheck;
public LayerMask groundLayers;
private float groundCheckRadius = 0.2f;
private void Awake()
{
rigi = GetComponent<Rigidbody2D>();
anim = this.GetComponent<Animator> ();
}
void Start()
{
}
void Update()
{
}
void FixedUpdate()
{
try
{
float move = Input.GetAxis("Horizontal");
rigi.GetComponent<Rigidbody2D>().velocity = new Vector2
(move * maxSpeed, GetComponent<Rigidbody2D>().velocity.y);
this.anim.SetFloat("Speed",Mathf.Abs(move));
if((move > 0.0f && isFacingRight == false) ||
(move < 0.0f && isFacingRight == true))
{
Flip ();
}
}
catch(UnityException error)
{
Debug.LogError(error.ToString());
}
}
void Flip()
{
isFacingRight = !isFacingRight;
Vector3 playerScale = transform.localScale;
playerScale.x = playerScale.x * -1;
transform.localScale = playerScale;
}
}
You need to use the Input.touches to detect the screen touch.
Maybe in this case you should detect if the player is pressing the right/left side of the screen and moving it accordingly. You can do that by comparing the touch position, something like input.touches[0].position.x < Screen.width/2 to move right for example.
https://docs.unity3d.com/ScriptReference/Input-touches.html
Just a piece of advice, do not use GetComponent inside the update method. In this case you don't actually need it because you already have the references on the awake method.
I'm making a 2D Tower Defense game and want my towers to launch a prefab at minions. However it currently only spawns my desired prefab, but doesn't move it.
My two scripts:
public class Attacker : MonoBehaviour {
// Public variables
public GameObject ammoPrefab;
public float reloadTime;
public float projectileSpeed;
// Private variables
private Transform target;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnTriggerEnter(Collider co){
if (co.gameObject.tag == "Enemy" || co.gameObject.tag == "BlockTower") {
Debug.Log("Enemy tag detected");
if(this.gameObject.tag == "Enemy" && co.gameObject.tag != "Enemy"){
Debug.Log("This is an Enemy");
// Insert for Enemey to attack Block Towers.
}
if(this.gameObject.tag == "Tower" && co.gameObject.tag != "BlockTower"){
Debug.Log("This is a Tower");
Tower Tower = GetComponent<Tower>();
Tower.CalculateCombatTime(reloadTime, projectileSpeed);
Transform SendThis = co.transform;
Tower.SetTarget(SendThis);
}
}
}
}
and
public class Tower : MonoBehaviour {
private Transform target;
private float fireSpeed;
private double nextFireTime;
private GameObject bullet;
private Attacker source;
// Use this for initialization
public virtual void Start () {
source = this.GetComponent<Attacker> ();
}
// Update is called once per frame
public virtual void Update () {
if (target) {
Debug.Log("I have a target");
//if(nextFireTime <= Time.deltaTime)
FireProjectile ();
}
}
public void CalculateCombatTime(float time, float speed){
Debug.Log("Calculate Combat Speed");
nextFireTime = Time.time + (time * .5);
fireSpeed = speed;
}
public void SetTarget(Transform position){
Debug.Log("Set Target");
target = position;
}
public void FireProjectile(){
Debug.Log("Shoot Projectile");
bullet = (GameObject)Instantiate (source.ammoPrefab, transform.position, source.ammoPrefab.transform.rotation);
float speed = fireSpeed * Time.deltaTime;
bullet.transform.position = Vector3.MoveTowards (bullet.transform.position, target.position, speed);
}
}
Basicly Attacker detects the object that collides with it, then if its tag is Tower it will send the information to Tower. My debug shows that every function works, even "Debug.Log("Shoot Projectile");" shows up.
However it doesn't move towards my target so I guess "bullet.transform.position = Vector3.MoveTowards (bullet.transform.position, target.position, step);" is never being executed?
Vector3.MoveTowards only moves the object once, it's just a instant displacement when the FireProjectile is called.
You need to create some kind of projectile script with an Update() function to make it move over time.
Here is an example:
public class Projectile : MonoBehaviour
{
public Vector3 TargetPosition;
void Update()
{
transform.position = Vector3.MoveTowards(transform.position, TargetPosition, speed * Time.DeltaTime);
}
}
Then right after your bullet instantiation, set the target:
bullet.GetComponent<Projectile>().TargetPosition = target.position;
Hope it helps.
You have to update the position of the bullet. You are only moving when you create the bullet.
Try to make a list of bullets and use the update function to change the position.