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.
Related
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.
How do I make my GameObject move towards another GameObject using Vector3.MoveTowards method?
Heres my current code:
void update()
{
TargetObject.transform.position = Vector3.MoveTowards (TargetObject.transform.position, Cube.transform.position , MaxDistanceDelta);
}
void Update() {
myGameObject.transform.position = Vector3.MoveTowards(myGameObject.transform.position, targetObject.transform.position, Time.deltaTime * speed);
}
myGameObject - object you want to move
targetObject - object you are moving to
speed - float value to set the speed
First, let's see the details and parameters of the method:
MoveTowards(Vector3 current, Vector3 target, float maxDistanceDelta);
Understanding the parameters
Vector3 current: 3D vector of the object position (example: new Vector(0,0,1))
Vector3 target: 3D vector of the target position (example: new Vector(3,4,5))
maxDistanceDelta: maximum distance that the object will move when the method is called. (Example: if maxDistanceDelta is 1, the object will move 1 unit every time it's called. In case we are not using Time.deltaTime it would move 50 units a second if the frame rate is 50)
Note: If the actual distance remaining is less than maxDistanceDelta, it will be placed on target position. Meaning the object will no longer move unless the target position changes.
Example:
Declaring the variables:
public float speed;
public Transform target;
Using the method:
transform.position = Vector3.MoveTowards(
transform.position,
target.position,
speed * Time.deltaTime
);
I have tried both of these C#scripts to rotate my directional light:
using System.Collections;
using UnityEngine;
public class LightRotator : MonoBehaviour
{
void Update ()
{
transform.rotation = Quaternion.Euler(transform.eulerAngles.x + 1.0f,
transform.eulerAngles.y,
transform.eulerAngles.z);
}
}
and
using System.Collections;
using UnityEngine;
public class LightRotator : MonoBehaviour
{
void Update ()
{
transform.localEulerAngles = new Vector3(transform.localEulerAngles.x + 1.0f,
transform.localEulerAngles.y,
transform.localEulerAngles.z);
}
}
They both seem to function exactly the same: If I change transform.eulerAngles.y to transform.eulerAngles.y + 0.5f, the light will rotate along the y-axis, and the same works for the z-axis. However, when I try to do this with the x-axis, it will rotate until it hits 90º, at which point it will continue to attempt rotation but it immediately and continuously shoved back to 90º. If I reverse the direction, it does the same thing at -90º. For example, the rotation might be: 88.5,89.0,89.5,90.0, 90.5, 89.93, 90.24, 89.4, etc.
What is causing this clamping and how do I fix it?
I think this is what you are looking for: http://answers.unity3d.com/questions/187073/rotation-locks-at-90-or-270-degrees.html
In order to fix your problem, you need to use an additional vector, change it inside Update every frame, and then pass it to the eulerAngles propriety of the transform.
Vector3 vect = Vector3.zero;
float rotationSpeed = 10f;
void Start () {
vect = transform.eulerAngles; //Set the vect rotation equal to the game object's one
}
void Update ()
{
vect.x += rotationSpeed * Time.deltaTime;
//Pass unique eulerAngles representation to the object without letting Unity change it
transform.eulerAngles = vect;
}
This happens btw because there're multiple euler angles representation of a single physical rotation in the 3D space, and when you work directly on the eulerAngles propriety of the transform, Unity makes some work behind the scenes, which can lead to a gimbal lock.
Use Quaternions. It's what Unity3d uses internally and doesn't have any of the side effects of euler angles.
using System.Collections;
using UnityEngine;
public class LightRotator : MonoBehaviour
{
public Vector3 RotationAxis = Vector3.right;
Quaternion _startRotation;
float _rotationIncrement = 0;
void Start()
{
_startRotation = transform.rotation;
}
void Update ()
{
Quaternion rotationMod =
Quaternion.AngleAxis(_rotationIncrement, RotationAxis);
_rotationIncrement += 1;
transform.rotation = _startRotation * rotationMod;
}
}
However, you probably want to use something like Quaternion.RotateTowards or Quaternion.Lerp along with Time.time and a rate. You will get much smoother results that way.
if you only want to rotate along the X-axis then set the other axis as 0.
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 ;)
Does anyone have a good jumping script for 2d games in unity? The code I have works but still is far from jumping, it looks like it is flying.
using UnityEngine;
using System.Collections;
public class movingplayer : MonoBehaviour {
public Vector2 speed = new Vector2(10,10);
private Vector2 movement = new Vector2(1,1);
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
float inputX = Input.GetAxis ("Horizontal");
float inputY = Input.GetAxis ("Vertical");
movement = new Vector2(
speed.x * inputX,
speed.y * inputY);
if (Input.GetKeyDown ("space")){
transform.Translate(Vector3.up * 260 * Time.deltaTime, Space.World);
}
}
void FixedUpdate()
{
// 5 - Move the game object
rigidbody2D.velocity = movement;
//rigidbody2D.AddForce(movement);
}
}
Usually for jumping people use Rigidbody2D.AddForce with Forcemode.Impulse. It may seem like your object is pushed once in Y axis and it will fall down automatically due to gravity.
Example:
rigidbody2D.AddForce(new Vector2(0, 10), ForceMode2D.Impulse);
The answer above is now obsolete with Unity 5 or newer. Use this instead!
GetComponent<Rigidbody2D>().AddForce(new Vector2(0,10), ForceMode2D.Impulse);
I also want to add that this leaves the jump height super private and only editable in the script, so this is what I did...
public float playerSpeed; //allows us to be able to change speed in Unity
public Vector2 jumpHeight;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update ()
{
transform.Translate(playerSpeed * Time.deltaTime, 0f, 0f); //makes player run
if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space)) //makes player jump
{
GetComponent<Rigidbody2D>().AddForce(jumpHeight, ForceMode2D.Impulse);
This makes it to where you can edit the jump height in Unity itself without having to go back to the script.
Side note - I wanted to comment on the answer above, but I can't because I'm new here. :)
Use Addforce() method of a rigidbody compenent, make sure rigidbody is attached to the object and gravity is enabled,
something like this
gameObj.rigidbody2D.AddForce(Vector3.up * 10 * Time.deltaTime); or
gameObj.rigidbody2D.AddForce(Vector3.up * 1000);
See which combination and what values matches your requirement and use accordingly.
Hope it helps