Trying to create a random Vector3 in Unity - c#

I am trying to make a random Vector3, but Unity is giving me this error: UnityException: Range is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call it in Awake or Start instead. Called from MonoBehavior 'particleMover'.
This is my code:
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using UnityEngine;
public class particleMover : MonoBehaviour
{
public float moveSpeed;
public float temperature;
public Rigidbody rb;
public Transform tf;
static private float[] directions;
// Start is called before the first frame
void Start()
{
System.Random rnd = new System.Random();
float[] directions = { rnd.Next(1, 360), rnd.Next(1, 360), rnd.Next(1, 360) };
}
// Update is called once per frame
void Update()
{
Vector3 direction = new Vector3(directions[0], directions[1], directions[2]);
direction = moveSpeed * direction;
rb.MovePosition(rb.position + direction);
}
}

Vector3 direction = Random.insideUnitSphere;
And you used (1, 360) and it seems you are confusing direction with rotation.
Vector3(x, y, z) - x, y, z are position values, not angles.
In addition, you need to use Time.deltaTime
direction = moveSpeed * direction * Time.deltaTime;
More info: https://docs.unity3d.com/ScriptReference/Time-deltaTime.html
Updated answer:
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using UnityEngine;
public class particleMover : MonoBehaviour
{
public float moveSpeed;
public float temperature;
public Rigidbody rb;
public Transform tf;
private Vector3 direction = Vector3.zero;
void Start()
{
direction = Random.insideUnitSphere;
}
void Update()
{
rf.position += direction * moveSpeed * Time.deltaTime;
// If this script is attached to tf object
// transform.position += direction * moveSpeed * Time.deltaTime;
}
}

Related

I need run add 1 to my var every 1 second in csharp without stopping the program

I want to add 1 to a variable meters when ever 1 seconds passed. Task.Delay wont work for some reason.
Here is all my code. Unfortunely im only a beginner at csharp so if you want make you can give me feedback on how to make it better.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movement : MonoBehaviour
{
public int movementSpeed = 6;
private Rigidbody2D rb;
//the variable i want to add 1 to:
public int meters;
public double speeding = 5;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
Ymovement();
void Ymovement()
{
var movement = Input.GetAxis("Vertical");
transform.position += new Vector3(0, movement, 0) * Time.deltaTime * movementSpeed;
}
}
}
This is a pretty typical use case for InvokeRepeating:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movement : MonoBehaviour
{
public int movementSpeed = 6;
private Rigidbody2D rb;
//the variable i want to add 1 to:
public int meters;
public double speeding = 5;
void Start()
{
rb = GetComponent<Rigidbody2D>();
InvokeRepeating("IncreaseMeters", 1f, 1f);
}
void Update()
{
Ymovement();
}
void Ymovement()
{
var movement = Input.GetAxis("Vertical");
transform.position += new Vector3(0, movement, 0) * Time.deltaTime * movementSpeed;
}
void IncreaseMeters()
{
meters += 1;
}
}

Would like advice on SOLID principles in my Unity C# script

I am working to understand SOLID, and want to know how my Unity C# script could be better formatted to align with the principles. I will provide the script and then an explanation:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController controller;
public float speed = 12f;
public float gravity = -9.81f;
Vector3 velocity;
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
private bool isGrounded;
void Update()
{
GroundCheck();
Movement();
Gravity();
}
private void GroundCheck()
{
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
if(isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}
}
private void Movement()
{
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
Vector3 move = transform.right * x + transform.forward * z;
controller.Move(move * speed * Time.deltaTime);
}
private void Gravity()
{
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
}
This is a script that handles movement of a character, but additionally performs ground checks and gravity of the player. I have seen interfaces used when adding new functionality, and new classes as well in the same script, but I thought for the purposes of this code it would be best to separate each functionality into a function and have them all call from update of the PlayerMovement class. I decided to use one class because I was wary of running three classes with three Update methods in this one script for performance reasons. Is there a better way I should approach the organization of this script from a SOLID point of view? My thought process was that if I wanted to extend these functionalities I would be able to do so in each function, and if I needed new functionality I could create more functions.
you can have one separate class that has the GroundCheck(), Movement(), Gravity() methods, and then you can access that class from the PlayerMovement class. if you make your methods static you will be able to access them. And that way you will have your public and private fields in PlayerMovement class and Update() method. So you call the methods in Update() and add the needed arguments in the brackets.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController controller;
public float speed = 12f;
public float gravity = -9.81f;
Vector3 velocity;
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
private bool isGrounded;
Movement movement;
void Start()
{
movement = FindObjectOfType<Movement>();
}
void Update()
{
movement.GroundCheck(isGrounded, groundCheck, groundDistance, groundMask, velocity);
movement.Movement(this.gameObject, controller, speed);
movement.Gravity(velocity, gravity, controller);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour
{
static public void GroundCheck(bool isGrounded, Transform groundCheck, float groundDistance, LayerMask groundMask, Vector3 velocity)
{
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
if(isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}
}
static public void Movement(GameObject playerMovement, CharacterController controller, float speed)
{
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
Vector3 move = playerMovement.transform.right * x + playerMovement.transform.forward * z;
controller.Move(move * speed * Time.deltaTime);
}
static public void Gravity(Vector3 velocity, float gravity, CharacterController controller)
{
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
}

I can't make my player move forward and backward! What is the problem?

I have been trying to create a video game but I stuck in this tutorial, in the tutorial it shows us to use input actions addon (What that does is it makes W-A-S-D or joystick type of keys easy to use) but even I watched the video after 3rd time I couldn't find the mistake! the problem is that I am not able to move my player forward or backward, I can only move it right and left. Please help I have tried so many things, like restarting the program or changing some code but it's not working can you help me to fix it?
Here is the first code to take the WASD commands from the addon script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InputManager : MonoBehaviour
{
//Takes the wasd controls from addon
InputWASD playerControls;
public Vector2 movementInput;
public float verticalInput;
public float horizontalInput;
private void OnEnable()
{
if (playerControls == null)
{
playerControls = new InputWASD();
playerControls.PlayerMovement.Movement.performed += i => movementInput = i.ReadValue<Vector2>();
}
playerControls.Enable();
}
private void OnDisable()
{
playerControls.Disable();
}
public void HandleAllInputs()
{
HandleMovementInput();
//TODO: HandleJumpInput
// HandleAttackInput
// HandleDashInput
// HandleAbilityInput
}
private void HandleMovementInput()
{
verticalInput = movementInput.y;
horizontalInput = movementInput.x;
}
}
Here is the second code to use keys in movement:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerAct : MonoBehaviour
{
InputManager inputManager;
Vector3 moveDirection;
Transform cameraObject;
Rigidbody playersRB;
public float moveSpeed = 6f;
public float rotationSpeed = 15f;
private void Awake()
{
inputManager = GetComponent<InputManager>();
playersRB = GetComponent<Rigidbody>();
cameraObject = Camera.main.transform;
}
public void HandleAllAction()
{
HandleMovement();
HandleRotation();
}
private void HandleMovement()
{
moveDirection = cameraObject.forward * inputManager.verticalInput;
moveDirection = moveDirection + cameraObject.right * inputManager.horizontalInput;
moveDirection.Normalize();
moveDirection.y = 0;
moveDirection = moveDirection * moveSpeed;
Vector2 movementVelocity = moveDirection;
playersRB.velocity = movementVelocity;
}
private void HandleRotation()
{
Vector3 targetDirection = Vector3.zero;
targetDirection = cameraObject.forward * inputManager.verticalInput;
targetDirection = targetDirection + cameraObject.right * inputManager.horizontalInput;
targetDirection.Normalize();
targetDirection.y = 0;
if (targetDirection == Vector3.zero)
{
targetDirection = transform.forward;
}
Quaternion targetRotation = Quaternion.LookRotation(targetDirection);
Quaternion playerRotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
transform.rotation = playerRotation;
}
}
Here is the third and last code to use first 2 codes:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMain : MonoBehaviour
{
//Calling scripts
InputManager inputManager;
PlayerAct playerAct;
private void Awake()
{
inputManager = GetComponent<InputManager>();
playerAct = GetComponent<PlayerAct>();
}
private void Update()
{
inputManager.HandleAllInputs();
}
private void FixedUpdate()
{
playerAct.HandleAllAction();
}
}
I did what the man told me (in the tutorial) but mine is not working!
sometime maybe the video is so old and unity is keep updating so some code maybe is not work anymore , maybe you should use the getinput system like float x= Input.GetAxis("Horizontal")); and float z = Input.GetAxis("Vertical"); this two is use characterController and let see how it work

GameObject.transform.position not working properly in Unity

I am making a game in unity and i want to get the position of the player so i use the code for the enemy:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyScript : MonoBehaviour
{
public GameObjetct player;
void Start()
{
Debug.Log(player.transform.position.x);
}
}
I have a spawner and here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnEnemies : MonoBehaviour
{
public GameObject enemy;
float randX;
float randY;
Vector2 whereToSpawn;
public float spawnRate = 2f;
float nextSpawn = 0.0f;
void Update()
{
if (Time.time > nextSpawn)
{
nextSpawn = Time.time + spawnRate;
randX = Random.Range(-6.36f, 6.36f);
randY = Random.Range(-4.99f, 4.99f);
whereToSpawn = new Vector2(randX, randY);
Instantiate (enemy, whereToSpawn, Quaternion.identity);
}
}
}
But when i run it, it always gives me (0, 0, 0). Why do i get 0 and how can i fix it ( get the current position of the player )?
Probably your player variable of enemy is not correctly assigned.
Try to assign the player GameObject variable to your SpawnEnemies object, and let this one assign the player variable to the enemies script.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnEnemies : MonoBehaviour
{
public GameObject enemy;
float randX;
float randY;
Vector2 whereToSpawn;
public float spawnRate = 2f;
float nextSpawn = 0.0f;
public GameObject player = null; //Remember to assign this through the editor!
void Update()
{
if (Time.time > nextSpawn)
{
nextSpawn = Time.time + spawnRate;
randX = Random.Range(-6.36f, 6.36f);
randY = Random.Range(-4.99f, 4.99f);
whereToSpawn = new Vector2(randX, randY);
GameObject enemy = Instantiate (enemy, whereToSpawn, Quaternion.identity);
enemy.player = this.player; //here you can assign to each new created enemy your player position on runtime.
}
}
}

Vector2' does not contain a definition for 'transform' and no accessible extension method 'transform' accepting a first argument of type 'Vector2'

here is my code (the problem is from transform.position = Vector3.MoveTowards(transform.position, mousePosition.transform.position, step);)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MouseDirection : MonoBehaviour
{
public Vector2 mousePosition;
public GameObject Player;
public float speed;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Vector2 mousePosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
float step = speed * Time.deltaTime;
if (Input.GetMouseButtonDown(0)){
transform.position = Vector3.MoveTowards(transform.position,
mousePosition.transform.position, step);
}
}
}
You can just use Input.mousePosition which is Vector3 you do not need a local variable for this.
transform.position = Vector3.MoveTowards(transform.position, Input.mousePosition, step);
hope this helps

Categories

Resources