Moving objects into random places by using functions - c#

I'm writing a code of moving a object to random places.
I made a function which decides the random coordinates and returns it.
However, I think the function and is not connected together.
This is what I tried...
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour
{
public float speed;
Vector3 target;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Vector3 target = random(target);
transform.position = Vector3.MoveTowards(transform.position, target, Time.deltaTime * speed);
}
Vector3 random(Vector3 target)
{
float min = -100.0f;
float max = 100.0f;
float randomX = Random.Range(min, max);
float randomZ = Random.Range(min, max);
Vector3 target = new Vector3(randomX, 10.0f, randomZ);
return target;
}
}
And this is the error message I got.
Assets\Movement.cs(31,17): error CS0136: A local or parameter named 'target' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
How can I fix this?

The problem is you define a new target variable inside random method. You have defined it as argument in method body before. Change one of them.

It is not really a problem with unity but with compiler.
Inside the random(Vector3 target) and void Update() methods you are defining new "target" variables like this:
Vector3 target
so the compiler is telling you that this is not allowed. If you want to update the target variable then remove the "Vector3" infront or choose a new name.
It is not clear how this function is meant to work but I think it is good to declare the target on start or declare it public so you can assign a start position to it.
I think what you want is something like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour
{
public float speed;
// OPTIONAL: declare public so the editor will let you set a position
public Vector3 target;
// Start is called before the first frame update
void Start()
{
// OPTIONAL: you can set a start position
target = Vector3.zero;
}
// Update is called once per frame
void Update()
{
target = random(target);
transform.position = Vector3.MoveTowards(transform.position, target, Time.deltaTime * speed);
}
Vector3 random(Vector3 par)
{
float min = -100.0f;
float max = 100.0f;
float randomX = Random.Range(min, max);
float randomZ = Random.Range(min, max);
return new Vector3(randomX, 10.0f, randomZ);
}
EDIT: You do not really need a parameter to the "random" function now. So maybe you can remove it

The reason you are getting this error is because you have already declared Vector3 target as a class member outside of the random and update methods.
If you are coming from a language like JavaScript, you can do it by declaring the same var variable name inside an inner scope but in C# it's not possible.

Related

Got 2 errors with 'start' and 'update' error CS0111: Type 'Enemy' already defines a member called 'Start' with the same parameter types how can i fix?

Got 2 errors from 1 script and dont know whats happening.
If anyone can help that would be great.
Error is in the title and the other one is the same except instead of 'Start' its 'Update'
Thanks for reading!!
using UnityEngine;
public class Enemy : MonoBehaviour
{
public float health = 50f;
private Rigidbody rb;
// Start is called before the first frame update
void Start()
{
rb = this.GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
Vector3 direction = player.position - transform.position;
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
float y = Quaternion.identity.eulerAngles.y;
float z = Quaternion.identity.eulerAngles.z;
rb.rotation = Quaternion.Euler(angle, y, z);
}
}
Using the override operator should get rid of the compiler errors, but I'm not a Unity dev so I'm not sure if Unity will treat your class in the correct way. Here's how you would do it:
override void Start()
{
...
}
// Update is called once per frame
override void Update()
{
...
}
You can read more about the override operator here: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/override
I also found this article and it declares Start as an IEnumerator rather than a void so that may fix it too.

How can I share data from onTriggerEnter method to smoothly move the position of a game object, using Update method?

enter image description hereI am able to set Y axis of my player with a simple transform.position call, in a single step, all within onTriggerEnter method, but the motion has a single step and is therefore jerky. Now I am trying to make the motion smooth by putting the transform.position function in an Update method within the same class. However, it seems that the position values determined/updated by onTriggerEnter method are not accessible in the Update function. If I print the x and z values to console, they contain expected values from onTriggerEnter function, but appear to be 0 when I print to console from the update function.
Any ideas of what I am doing wrong?
I would never call myself a programmer, so assume the worst :-)
Thanks in advance for any help!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Step1SetElevation : MonoBehaviour
{
private float moveSpeed = 3f;
private float currX = 0.0f;
private float currZ = 0.0f;
private Vector3 currentPos;
private GameObject player;
private Collider other;
void OnTriggerEnter(Collider other)
{
player = GameObject.FindWithTag("Player");
currentPos = GameObject.Find("PlayerController").transform.position;
currX = currentPos.x;
currZ = currentPos.z;
}
void Update()
{
player = GameObject.FindWithTag("Player");
player.transform.position = new Vector3(currX, 3.4f, currZ) * Time.deltaTime * moveSpeed;
}
}
I believe your problem may be that you are using OnTriggerEnter() to set the position you want your player to move to, this will be called on the frame your player enters your trigger but then won't be called again until the player left and re-entered...
If you instead use OnTriggerStay() - something like
void Start(){ // this lookup can be expensive so lets only do it once
player = GameObject.FindWithTag("Player");
playerController = GameObject.Find("PlayerController");
}
void OnTriggerStay(Collider other){ // this is called once per frame that a collider remains in a trigger
if(other.gameObject.tag == "Player"){ // just in case anything else ever enters the collider
currentPos = playerController.transform.position;
currX = currentPos.x;
currZ = currentPos.z;
}
}
void FixedUpdate(){ // it's generally advised to move objects in fixed update
player.transform.position = new Vector3(currX, 3.4f, currZ) * Time.fixedDeltaTime * moveSpeed;
}

rb.addforce not responding even though collision works

how are you doing?
I am working on a simple mechanic of knockback where if my character collides with the name "enemy", the players rigidbody which is paraphrsased as (rb), has force added 'back'.
Here is my code, Please refer to where I outline with asterisk.
public class Move : MonoBehaviour
{
public float speed;
private Rigidbody rb;
public int health;
private float knockback;
// Use this for initialization
void Start()
{
rb = GetComponent<Rigidbody>();
knockback = 2f;
}
void OnCollisionEnter(Collision col)
{
if (col.gameObject.name == "enemy")
{
health = health - 20; //**this works**
rb.AddRelativeForce(Vector3.forward * knockback); //**but this doesnt :c **
}
}
void death()
{
if (health <= 0)
{
print("i died");
}
}
void playerWalk()
{
var x = Input.GetAxis("Horizontal") * Time.deltaTime * 75f;
var z = Input.GetAxis("Vertical") * Time.deltaTime * 5f;
transform.Rotate(0, x, 0);
transform.Translate(0, 0, z);
}
void Update()
{
death();
playerWalk();
}
}
The problem is as you may have guessed, My triggers do not work.
My health = health - 20; line works but my rb.addforce doesn't.
What could be the problem here? Thank you :)
edit 2#
Just want to edit this and say That I have figured out the problem. The problem was that my float value just was not high enough xD
As you wrote the snippet, ´rb´ is not a field, but a local variable inside the ´Start´ method. If you are getting an exception in the menctioned line, maybe it is because of this. If you want ´rb´ to be a field, accesible all arround the class methods, you'll need to declare it in the class body, like this:
public int health;
private float knockback;
private RigidBody rb;
// (...) the rest of your code
If this is not the case, just tell me and give us more info on your problem.
Try removing the deltaTime:
rb.AddRelativeForce(Vector3.forward * knockback);
The default ForceMode for AddRelativeForce is AddForce and does not require time scaling.
I am not expert but this is my answer....
You attached rigidbody to the transform....so changing rigidbody position equal to transform position...
You calling two methods in update...so they going to be continuously called....so you move transform forward direction with uparrow key.. But you add force only at collision enter...collision enter is called only one time but playerwalk method is called continuously...that's why add force is not recognised.... Check this link
http://unityweltech.blogspot.com/2018/09/rbforce-is-not-responding.html?m=1

Unity2D - Companion

When reading this, keep in mind I'm new to both programming and Unity, so I might be missing some terms or tools Unity offer. Please elaborate your answers in an ELI5 manner. Thanks in advance!
I am currently working on some game-physics for a small personal project. Currently I've created a platform, a character and what should be, a following companion.
However, since I'm still not on a level, where I can create perfect code on own hand, I found an "enemy" script and tried to modify it a bit.
It Works to an extend, but it needs some tweaks which I hope I can help aquire with you guys.
This is how it looks now (the orange square is the companion)
It follows the player, and I can tweak the speed to fit as a companion, and not a player. However, as the Picture presents, the companion runs for the center of the player. What I want to create is a companion which follows the player, but still keeps a small gap from the player.
My first thoughts was to create some kind of permanent offset, but I fail to figure out how to do this without messing up the follow function.
I hope you can help me, it will be much appreciated!
Here's the code for reference.
Code attached to Player:
using UnityEngine;
using System.Collections;
public class PlayerCompanion : MonoBehaviour
{
//In the editor, add your wayPoint gameobject to the script.
public GameObject wayPoint;
//This is how often your waypoint's position will update to the player's position
private float timer = 0.5f;
void Update ()
{
if (timer > 0) {
timer -= Time.deltaTime;
}
if (timer <= 0) {
//The position of the waypoint will update to the player's position
UpdatePosition ();
timer = 0.5f;
}
}
void UpdatePosition ()
{
//The wayPoint's position will now be the player's current position.
wayPoint.transform.position = transform.position;
}
}
Code attached to companion:
using UnityEngine;
using System.Collections;
public class FollowerOffset : MonoBehaviour {
//You may consider adding a rigid body to the zombie for accurate physics simulation
private GameObject wayPoint;
private Vector3 wayPointPos;
//This will be the zombie's speed. Adjust as necessary.
private float speed = 10.0f;
void Start ()
{
//At the start of the game, the zombies will find the gameobject called wayPoint.
wayPoint = GameObject.Find("wayPoint");
}
void Update ()
{
wayPointPos = new Vector3(wayPoint.transform.position.x, transform.position.y, wayPoint.transform.position.z);
//Here, the zombie's will follow the waypoint.
transform.position = Vector3.MoveTowards(transform.position, wayPointPos, speed * Time.deltaTime);
}
}
bump, I guess ? :)
You can use smooth follow script. I have created a sample class for you. This class has features to follow any given gameobject with some delay and offset. You will have to tweak some values according to your need.
using UnityEngine;
using System.Collections;
public class PlayerCompanion : MonoBehaviour
{
[SerializeField]
private GameObject wayPoint;
[SerializeField]
public Vector3 offset;
public Vector3 targetPos;//Edit: I forgot to declare this on firt time
public float interpVelocity;
public float cameraLerpTime = .1f;
public float followStrength = 15f;
// Use this for initialization
void Start ()
{
//At the start of the game, the zombies will find the gameobject called wayPoint.
wayPoint = GameObject.Find("wayPoint");
offset = new Vector3 (5,0,0);//input amount of offset you need
}
void FixedUpdate () {
if (wayPoint) {
Vector3 posNoZ = transform.position;
Vector3 targetDirection = (wayPoint.transform.position - posNoZ);
interpVelocity = targetDirection.magnitude * followStrength;
targetPos = transform.position + (targetDirection.normalized * interpVelocity * Time.deltaTime);
transform.position = Vector3.Lerp (transform.position, targetPos + offset, cameraLerpTime);
}
}
}
Attach this class to your player companion, play with different values.
To preserve object orientation your companion schould not be anyways child of your main character.
Your wayPoint doesn't needs to be a GameObject but a Transform instead and your code will looks like better.
If your game is a 2D platform your and your companion needs to be backwards your player it probabli applys to just one axis (X?) so you can decrement your waiPoint in a more directly way by calculating it on your UpdatePosition function like this:
wayPoint.position = transform.position * (Vector3.left * distance);
where your "distance" could be a public float to easily setup.
so on your companion script Update just do:
transform.position = Vector3.MoveTowards(transform.position, wayPoint.position, speed * Time.deltaTime);
I can't test it right now so you could have problems with Vector3 multiply operations, just comment and I'll try to fix as possible ;)

Move simple Object in Unity 2D

I'm trying to move a simple Object in Unity but I get the following error message:
cannot modify the return value of unityengine.transform.position because itar is not variable
Here is my code:
using UnityEngine;
using System.Collections;
public class walk : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
float movespeed = 0.0f;
movespeed++;
transform.position.x = transform.position.x + movespeed;
}
}
You can't assign the x value on position directly as it's a value type returned from a property getter. (See: Cannot modify the return value error c#)
Instead, you need to assign a new Vector3 value:
transform.position = new Vector3(transform.position.x + movespeed, transform.position.y);
Or if you're keeping most of the coordinate values the same, you can use the Translate method instead to move relatively:
transform.Translate(movespeed, 0, 0)
A slight improvement over Chris' answer:
transform.position = new Vector2(transform.position.x + movespeed * Time.deltaTime, transform.position.y);
Time.deltaTime the amount of time it's been between your two frames - This multiplication means no matter how fast or slow the player's computer is, the speed will be the same.

Categories