So I'm making a puzzle based game in which the player must use Trampolines which detect when the player jumps on top of it and bounces them up x amount of height.
However currently at the moment my code isn't working and stating error that
"Cannot modify the return value of 'UnityEngine.Rigidbody.velocity' because it is not a variable."
Wondering if any you guys know what could be done to fix this code and allow it to work to the purpose its needed for.
using UnityEngine;
using System.Collections;
public class small_trampoline_bounce : MonoBehaviour {
bool willBounce = false;
float bounceHeight = 10;
public Transform Player;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
if (willBounce)
{
Player.rigidbody.velocity.y = 0;
Player.rigidbody.AddForce (0, bounceHeight, 0, ForceMode.Impulse);
willBounce = false;
}
}
void OnCollisionEnter (Collision other)
{
if (other.gameObject.name == "Player")
{
willBounce = true;
}
}
}
To address the specific error you are getting - since velocity is a vector, you can't modify the returned vector and expect the stored vector to change. If you really want to set the velocity directly, you need to set the whole vector, not just a portion:
Player.rigidbody.velocity = new Vector3(0, 0, 0);
If you want to maintain previous x and z velocity, you can do this:
vector3 velocity = Player.rigidbody.velocity;
Player.rigidbody.velocity = new Vector3(velocity.x, 0, velocity.z);
Related
So in my game you are a sphere rolling down ramps, but if you go too fast and crash into a ledge the game freezes and the console gets spammed with the first error in the title followed by the second one. I managed to find what line of code caused this problem, here's that script:
public class FöljaBoll : MonoBehaviour
{
public GameObject player;
public float yOffset;
public float zOffset;
Transform playerPosition;
Transform cameraPosition;
// Start is called before the first frame update
void Start()
{
playerPosition = player.GetComponent<Transform>();
cameraPosition = gameObject.GetComponent<Transform>();
}
// Update is called once per frame
void Update()
{
if (playerPosition == null)
{
return;
}
cameraPosition.position = playerPosition.position + new Vector3(0, +yOffset, -zOffset);
}
private void FixedUpdate()
{
if (player == null)
{
return;
}
else
{
float speed = player.GetComponent<Rigidbody>().velocity.z + 6;
float targetFOV = (float)Math.Log(speed, 1.1) + 34;
GetComponent<Camera>().fieldOfView = Mathf.Lerp(GetComponent<Camera>().fieldOfView, targetFOV, (float)0.1);
}
}
}
So what it does is it sets the FOV based on the player speed through a logarithmic function in order for it to not get out of control at high speeds, but for some reason this part (I commented it out and wasn't able to recreate the errors):
GetComponent<Camera>().fieldOfView = Mathf.Lerp(GetComponent<Camera>().fieldOfView, targetFOV, (float)0.1);
triggers the error messages. If anyone could help me out here that would be awesome, thanks in advance! :)
I solved it myself by setting the bounciness of the Physics Material attached to both the ramps and the sphere to 0. This post: https://answers.unity.com/questions/9985/limiting-rigidbody-velocity.html said that bounciness combined with high velocities can cause problems and that seems to have been the problem.
I want my enemy to move back to starting position. He follows me until I get out of his range and then he just stops.
Also i want my skeleton to stop for like 5 sec, and then go back to starting point, any ideas ? I never did anything involving time, exept stopping it.
Here is my script for enemy:
Also here is a screenshoot of inspector on the skeleton: enemy
Here is my script for enemy:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class chase : MonoBehaviour
{
public Transform player;
private Animator anim;
public float LookRadius = 15f;
public Transform enemyStartPos;
// Use this for initialization
void Start()
{
anim = GetComponent<Animator>();
this.enemyStartPos.position = this.transform.position;
}
// Update is called once per frame
void Update()
{
if (!PauseMenu.GameIsPaused)
{
if (Vector3.Distance(player.position, this.transform.position) < 15)
{
Vector3 direction = player.position - this.transform.position;
direction.y = 0;
this.transform.rotation = Quaternion.Slerp(this.transform.rotation, Quaternion.LookRotation(direction), 0.1f);
anim.SetBool("isIdle", false);
if (direction.magnitude > 3)
{
this.transform.Translate(0, 0, 0.05f);
anim.SetBool("isWalking", true);
anim.SetBool("isAttacking", false);
}
else
{
anim.SetBool("isAttacking", true);
anim.SetBool("isWalking", false);
}
}
else
{
if (Vector3.Distance(this.enemyStartPos.position, this.transform.position) >1)
{
Vector3 direction = this.enemyStartPos.position - this.transform.position;
direction.y = 0;
this.transform.rotation = Quaternion.Slerp(this.transform.rotation, Quaternion.LookRotation(direction), 0.1f);
anim.SetBool("isIdle", false);
if (direction.magnitude > 1)
{
this.transform.Translate(0, 0, 0.05f);
anim.SetBool("isWalking", true);
anim.SetBool("isAttacking", false);
}
}
else
anim.SetBool("isIdle", true);
anim.SetBool("isAttacking", false);
anim.SetBool("isWalking", false);
}
}
}
private void OnDrawGizmosSelected()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, LookRadius);
}
}
Before you try to "code" this, think about it in terms of your program design. You have designed and implemented behavior that says "if the bot's position is within X units of the player's position, turn the bot and move it toward the player."
What you describe wanting to do next can be thought of in the same way (which should lead to similar code).. "else, if the bot's position is NOT within X units of the player's position, turn the bot and move it toward [origin]." Note, this means you need to define what [origin] is for the bot. Point being, it makes no difference in the code whether you are moving toward a player or some arbitrary fixed point. The code to move one transform toward another transform is the same.
For "wandering" it's essentially the same thought process: If bot is within X units of [origin] and not following player, pick a random direction and move that way. (better yet, pick a random direction and move that way for some amount of time so your bot doesn't just jitter around origin).
I finish making running game. But I placed obstacle like this :
This way makes phone frozen often. So I make a prefeb is made of obstacle object like this :
I want to use function SetActive(bool) to appear/disappear obstacle. Finally, How it works is My runner is at a standstill and background, obstacle, coin, juwel is moved. But My creator script has a big problem.
My Prolem :
As you see, This code create blank(red box) between two obstacle prefebs. I can't find problem. Plz help me...
Creator Script :
using UnityEngine;
using System.Collections;
public class CsPartCreator : MonoBehaviour {
int count = 1;
float timer = 0.0f;
// Use this for initialization
void Start () {
for (int i = 1; i < 26; i++)//set Deactive all object excluding first object (Because This object is watched at first.)
transform.GetChild(i).gameObject.SetActive(false);
}
// Update is called once per frame
void Update () {
timer += Time.deltaTime;
if (timer > 5f && count < 23)//every 5 seconds and count is smaller than the number of prefeb
{
transform.GetChild(count).gameObject.SetActive(true);//
count++;
timer = 0;
}
}
}
This is my Hierarchy :
I think , That missing prefab's Z value is more negative than background , Or you have used a sorting layer which is set to be behind background.
And Check if all obstacle gameobjects correctly orderered in Hirachy Part0, Part1, Part2, Part3 like that. Let me know if those are in correct order
Please check that :)
using UnityEngine;
using System.Collections;
using System.Linq;
using System.Collections.Generic;
public class CsPartCreator : MonoBehaviour
{
private GameObject player;
float timer = 0.0f;
private List<GameObject> obstacles;
void Awake()
{
player = GameObject.FindWithTag("Player");
obstacles = new List<GameObject>();
}
// Use this for initialization
void Start()
{
for (int i = 0; i < 26; i++)//set Deactive all object excluding first object (Because This object is watched at first.)
{
obstacles.Add(transform.GetChild(i).gameObject);
transform.GetChild(i).gameObject.SetActive(false);
}
}
// Update is called once per frame
void Update()
{
if (obstacles == null || obstacles.Count() == 0)
return;
var toActivate = obstacles.Where(x => x.transform.position.x > transform.position.x && x.transform.position.x < transform.position.x + 10).ToList(); // +10 is the range
foreach (GameObject go in toActivate)
{
go.SetActive(true);
obstacles.Remove(go);
}
}
}
Set player gameobject to "Player" tag as in image below
i wrote a script for my 2D car game for an infinite track. So i got a "killer" behind my car, that destroys all ground objects coming out the screen on the left and on the right i have a spawner that spawns all my blocky sprites in it and it works pretty good.
Here is my update function:
void Update()
{
if(Mathf.Round(this.transform.position.x) == limit)
{
//Debug.Log("Limit reached");
limit += 10;
Spawn();
}
}
I attached the script to my camera and i have a start limit set to 160 (because i already got 15 10x10 sprites as start). Everytime my spawner passes the x-axis-limit it spawns a new sprite at this position and sets the next limit 10 higher. This works good if I don't drive too fast. Because then it stops spawning and the world is cut off. When I drive back to get my spawner back into the already spawned area and drive slowly again to it, it works again. I believe the method is just to inefficient to spawn fast enough so I maybe need another style of doing it.
For the understanding here the rest of the script:
using UnityEngine;
using System.Collections;
public class Spawner : MonoBehaviour
{
public GameObject[] obj;
private int limit = 160;
public int yAxisValue = -1;
public bool isOnlyDirt;
private ArrayList rotationValues = new ArrayList();
void Start()
{
//Spawn ();
int value = 0;
for(int i = 0; i < 4; i++)
{
rotationValues.Add(value);
//Debug.Log(rotationValues[i]);
value += 90;
}
}
void Spawn()
{
Vector3 pos = new Vector3 (Mathf.Round(transform.position.x), yAxisValue, transform.position.z);
Quaternion rotation = new Quaternion (0, 0, 0, 0);
if(isOnlyDirt)
{
int zRot = (int)rotationValues[Random.Range(0, rotationValues.Count - 1)];
//Debug.Log(zRot);
rotation = new Quaternion(0, 0, zRot, 0);
}
var SpawnedGround = Instantiate(obj[Random.Range(0, obj.GetLength(0))], pos, rotation);
(SpawnedGround as GameObject).gameObject.tag = "Gro
I also have a one-liner to move my spawner in front of my car so it can spawn things:
public float yCoord;
void Start ()
{
this.transform.position = new Vector3 (transform.position.x + 160, -yCoord, transform.position.z);
}
I parented it so i just have to write it in the start function.
Any ideas to improve this one?
Thanks
Sorry can't post as comments. You should try
if(Mathf.Round(this.transform.position.x) >= limit)
instead of
if(Mathf.Round(this.transform.position.x) == limit)
I think the floating point precision is skipping the checking.
Basically this game is a brick breaker in which I will be giving a quick basic background about it. The game will spawn 10 bricks at random locations, and if the all hits the brick
once, the brick is destroyed. If all 10 bricks are destroyed then the user will be taken to the other scene (gamewon).
My main problem is that when I destroy all the bricks, I am not being redirected to the scene. However if I set the numberOfBricks to 1, it will work.. I can't really understand what's happening.
Thanks alot guys!
-HurpaDurpa
using UnityEngine;
using System.Collections;
public class BrickScript : MonoBehaviour {
public int position_x = 0;
public int position_y = 0;
public GameObject Brick;
public int brickDamage = 0;
public int numberOfBricks = 10;
// Use this for initialization
void Start () {
Brick = GameObject.Find ("Brick");
position_x = Random.Range (-6, 6);
position_y = Random.Range(-1, 4);
transform.position = new Vector3 (position_x, position_y, transform.position.z);
}
// Update is called once per frame
void Update () {
if (brickDamage == 1) { //destroy brick on 1 hit
numberOfBricks--;
Object.Destroy (gameObject); //so it will destroy the hit object
}
if (numberOfBricks == 0) {
Application.LoadLevel (1);
numberOfBricks = 10;//Variable resetted
}
}
void OnCollisionEnter(Collision collision)
{
brickDamage++;
}
}
This is happening because you seem to have attached the script above to each brick.
So what is really happening is when any one of your bricks get hit, the numberOfBricks reduces by 1, resulting the value going to 9. This will happen to each brick.
Rather, what you need to do is to keep this numberOfBricks counter in another script. In the OnCollisionEnter portion of your code, you should reduce the numberOfBricks variable in the other script by 1.
Do that and you'll see the result you expect.