I am very new to programming.. I tried to make a endless runner with unity and I am at the point now that I want to make platforms to spawn automatically. I followed a tutorial but whenever I reach the end no new platforms are being spawned ):
Here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TESTGAMEMANAGER : MonoBehaviour
{
private const float PLAYER_DISTANCE_SPAWN_LEVEL_PART = 50f;
[SerializeField] private Transform levelPart_Start;
[SerializeField] private List<Transform> levelPartList;
[SerializeField] private PlayerScript player;
private Vector3 lastEndPosition;
private void Awake()
{
lastEndPosition = levelPart_Start.Find("EndPoint").position;
int startingSpawnLevelParts = 5;
for (int i = 0; i < startingSpawnLevelParts; i++)
{
SpawnLevelPart();
}
}
private void Update()
{
if (Vector3.Distance(player.transform.position(), lastEndPosition) < PLAYER_DISTANCE_SPAWN_LEVEL_PART)
{
// Spawn another level part
SpawnLevelPart();
}
}
private void SpawnLevelPart()
{
Transform chosenLevelPart = levelPartList[Random.Range(0, levelPartList.Count)];
Transform lastLevelPartTransform = SpawnLevelPart(chosenLevelPart, lastEndPosition);
lastEndPosition = lastLevelPartTransform.Find("EndPoint").position;
}
private Transform SpawnLevelPart(Transform levelPart, Vector3 spawnPosition)
{
Transform levelPartTransform = Instantiate(levelPart, spawnPosition, Quaternion.identity);
return levelPartTransform;
}
}
It seems like that only at the start there are platforms but after some time I reach the end and fall down );
Anyone know how to fix that?
Unity Picture with problem
Related
I was making a platform that bounces the player after a certain period of time when the player touches it. I attached this code component to the GameObject, which is a tilemap, and it doesn't work properly. What's wrong with my code? The code and scriptable object are as follows.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ExplosionPlatform : PlatformBase
{
public float explosionPower = 20f;
public float waitTime = 1.5f;
public float colTime = 0f;
public bool isDamageOnce = false;
public Vector2 area = new Vector2(2, 2);
public Vector2 positionModify = new Vector2(1, 0);
private void OnCollisionEnter2D(Collision2D collision)
{
StartCoroutine(Explosion());
}
private IEnumerator Explosion()
{
Debug.Log("ASDF");
yield return new WaitForSeconds(waitTime);
Collider2D[] player = Physics2D.OverlapBoxAll(transform.position + (Vector3)positionModify, area, 0);
foreach (Collider2D col in player)
{
if (col.CompareTag("Player"))
{
col.gameObject.GetComponent<Rigidbody2D>().AddForce(Vector2.up * explosionPower, ForceMode2D.Impulse);
Damage();
isDamageOnce = true;
yield return new WaitForSeconds(3f);
isDamageOnce = false;
}
}
}
private void OnDrawGizmos()
{
Gizmos.color = Color.blue;
Gizmos.DrawWireCube(transform.position + (Vector3)positionModify, area);
}
}
I have confirmed that the code below works properly on GameObject, which is Unity 2d Sprite. Is there any way to use that code while using the tile map?
I did it many times,but maybe i forgot.I am trying to instantiate prefab,and scale it down but it doesnt take any effects.It only works if I scale original prefab,but then I am not able to Destroy this prefab.
public class PozicijaButona : MonoBehaviour
{
Vector2 pozicijaV;
float x, y;
Text tekstPozicije;
List<Vector2> lista = new List<Vector2>();
List<Sprite> slike1t, slike2t, slike3t, slike4t;
public GameObject instantacija;
private GameObject oznacenaSl;
Vector3 skala;
// Start is called before the first frame update
void Start()
{
tekstPozicije = GameObject.Find("Canvas/pozicija").GetComponent<Text>();
List<Vector2> lista = new List<Vector2>();
slike1t= new List<Sprite>();
for (int i = 0; i < HintoviMale.slikeT.Count; i++)
{
slike1t.Add(HintoviMale.slikeT[i]);
}
skala = transform.localScale;
instantacija.transform.localScale = skala;
Debug.Log("sjaa" + skala);
}
// Update is called once per frame
void Update()
{
}
private void OnMouseDown()
{
pozicijaV = transform.position;
x = transform.position.x;
y = transform.position.y;
string xT = x.ToString();
string yT = y.ToString();
// tekstPozicije.text=xT+","+yT;
tekstPozicije.text = pozicijaV.ToString();
Destroy(oznacenaSl);
}
public void klikNaPoziciju()
{
Debug.Log("broj itema u slici"+HintoviMale.slikeT.Count);
oznacenaSl = Instantiate (instantacija, new Vector2(-0.7f, -3.4f), Quaternion.identity);
// oznacenaSl.transform.localScale = skala;
oznacenaSl.GetComponent<SpriteRenderer>().sprite=HintoviMale.slikeT[0];
}
}
I did it many times,but maybe i forgot.I am trying to instantiate prefab,and scale it down but it doesnt take any effects.It only works if I scale original prefab,but then I am not able to Destroy this prefab.
You never call your function named "klikNaPoziciju", which contains the Instantiate call. You also have commented out the line that changes the localScale of the object named "oznacenaSl".
Here is a simple example of instantiating an object and modifying it's localScale:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InstantiateObjectExample : MonoBehaviour
{
public GameObject objectToInstantiate;
private GameObject instantiatedObject;
private void Awake()
{
CreateInstanceOfObject();
}
private void CreateInstanceOfObject()
{
instantiatedObject = Instantiate(objectToInstantiate, transform.position, Quaternion.identity);
instantiatedObject.transform.localScale = new Vector3(2f, 2f, 1f);
}
}
In the Unity Hierarchy, create an empty gameObject and attach the script to it. Then in the Inspector for the gameObject you just created, drag your prefab into the "Object to Instantiate" field.
EDIT:
OP mentioned they are calling their public method from an OnClick method in the Unity Editor. I'm not familiar with that approach, but another approach would be to use the OnMouseDown() function in your script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InstantiateObjectExample : MonoBehaviour
{
public GameObject objectToInstantiate;
private GameObject instantiatedObject;
private void OnMouseDown()
{
CreateInstanceOfObject();
}
private void CreateInstanceOfObject()
{
Debug.Log("Creating instance!");
instantiatedObject = Instantiate(objectToInstantiate, transform.position, Quaternion.identity);
instantiatedObject.transform.localScale = transform.localScale;
}
}
For this to work, make sure the object you attach the script to has a collider attached to it. Clicking on the collider will trigger the OnMouseDown() function.
I'm a Unity novice and I'm creating a small 2D shooting game on a school project and I already managed to have a functional shooting system in the main character that even bounces off some objects using Unity Physics.
I now wanted to integrate an aim line that will predict the trajectory of the bullet, including the bounces on objects (bubble-shooter style).
I found a script that uses Raycast and Line Renderer and it supposedly does this and I tried to integrate it into my gun script but although it does not give any error, it simply does not show anything when I test the game. I do not know if the problem is in the settings that I put in the Line Renderer Component or it is in the Script.
Could someone help me understand where my error is and point the right way?
My goal is:
My Line Renderer Component Definitions:
My Weapon Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(LineRenderer))]
public class Weapon : MonoBehaviour
{
[Range(1, 5)]
[SerializeField] private int _maxIterations = 3;
[SerializeField] private float _maxDistance = 10f;
public int _count;
public LineRenderer _line;
public Transform Firepoint;
public GameObject BulletPrefab;
public GameObject FirePrefab;
void Start()
{
_line = GetComponent<LineRenderer>();
}
// Update is called once per frame
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Shoot();
}
_count = 0;
_line.SetVertexCount(1);
_line.SetPosition(0, transform.position);
_line.enabled = RayCast(new Ray(transform.position, transform.forward));
}
void Shoot()
{
//shooting logic
var destroyBullet = Instantiate(BulletPrefab, Firepoint.position, Firepoint.rotation);
Destroy(destroyBullet, 10f);
var destroyFire = Instantiate(FirePrefab, Firepoint.position, Firepoint.rotation);
Destroy(destroyFire, 0.3f);
}
private bool RayCast(Ray ray)
{
RaycastHit hit;
if (Physics.Raycast(ray, out hit, _maxDistance) && _count <= _maxIterations - 1)
{
_count++;
var reflectAngle = Vector3.Reflect(ray.direction, hit.normal);
_line.SetVertexCount(_count + 1);
_line.SetPosition(_count, hit.point);
RayCast(new Ray(hit.point, reflectAngle));
return true;
}
_line.SetVertexCount(_count + 2);
_line.SetPosition(_count + 1, ray.GetPoint(_maxDistance));
return false;
}
}
Unity has two physics engines one for 2D and one for 3D. The script you provided relies on the 3D physics engine and won't work for 2D colliders. I edited your script to function with 2D colliders.
Either way make sure that all your game objects use the same physics system. Also the original script only shows the line renderer if it hits something. Best of luck!
using UnityEngine;
[RequireComponent(typeof(LineRenderer))]
public class Weapon : MonoBehaviour
{
[Range(1, 5)]
[SerializeField] private int _maxIterations = 3;
[SerializeField] private float _maxDistance = 10f;
public int _count;
public LineRenderer _line;
public Transform Firepoint;
public GameObject BulletPrefab;
public GameObject FirePrefab;
private void Start()
{
_line = GetComponent<LineRenderer>();
}
// Update is called once per frame
private void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Shoot();
}
_count = 0;
_line.SetVertexCount(1);
_line.SetPosition(0, transform.position);
_line.enabled = true;
RayCast(transform.position, transform.up);
}
private void Shoot()
{
//shooting logic
var destroyBullet = Instantiate(BulletPrefab, Firepoint.position, Firepoint.rotation);
Destroy(destroyBullet, 10f);
var destroyFire = Instantiate(FirePrefab, Firepoint.position, Firepoint.rotation);
Destroy(destroyFire, 0.3f);
}
private bool RayCast(Vector2 position, Vector2 direction)
{
RaycastHit2D hit = Physics2D.Raycast(position, direction, _maxDistance);
if (hit && _count <= _maxIterations - 1)
{
_count++;
var reflectAngle = Vector2.Reflect(direction, hit.normal);
_line.SetVertexCount(_count + 1);
_line.SetPosition(_count, hit.point);
RayCast(hit.point + reflectAngle, reflectAngle);
return true;
}
if (hit == false)
{
_line.SetVertexCount(_count + 2);
_line.SetPosition(_count + 1, position + direction * _maxDistance);
}
return false;
}
}
Well, I changed on the physics material of the bullet, the Friction to 0 and Bounciness to 1. Also on the rigidbody2D the linear drag, angular drag and gravity scale all to 0. Although it is not a perfect rebound it was very close to what I intend for the game. Thank you! Check it out: Game Gif
Only negative thing is that my bullet is not turning in the direction of the movement after the rebound. I tried to use transform.LookAt but didn`t work. This is my bullet script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bullet : MonoBehaviour
{
public float speed = 20f;
public Rigidbody2D myRigidbody;
// Start is called before the first frame update
void Start()
{
this.myRigidbody = this.GetComponent<Rigidbody2D>();
this.myRigidbody.velocity = transform.right * speed;
transform.LookAt(transform.position + this.myRigidbody.velocity);
}
}
But now i have this error: Error CS0034 Operator '+' is ambiguous on operands of type 'Vector3' and 'Vector2'
I'm making a basic basket ball game and i have a public boolean called dunkComplete which activated after the ball is dunked and is attaced to the ball script, i am trying to reference this boolean in a game manager script but for some reason even though dunkComplete becomes true its game manager counterpart doesn't, heres the game manager script for reference.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class game_manager : MonoBehaviour {
public GameObject Basket;
private float x_value;
private float y_value;
public GameObject ball;
private ball_script basketBallScript;
private bool dunkCompleteOperation;
// Use this for initialization
void Start () {
basketBallScript = ball.GetComponent<ball_script>();
Vector2 randomVector = new Vector2(Random.Range(-9f, 9f), Random.Range(0f, 3f));
Debug.Log(randomVector);
Instantiate(Basket, randomVector, transform.rotation);
Instantiate(ball, new Vector2(0, -3.5f), transform.rotation);
}
// Update is called once per frame
void Update () {
dunkCompleteOperation = basketBallScript.dunkComplete;
if (dunkCompleteOperation == true)
{
Vector2 randomVector = new Vector2(Random.Range(-9f, 9f), Random.Range(0f, 3f));
Instantiate(Basket, randomVector, transform.rotation);
}
}
}
Any help would be greatly apreciated thanks.
Your basketBallScript does not refer to the ball_script that the ball object that you instantiate. You should keep the reference to the GameObject that you created and then assign the basketBallScript.
Try this:
public class game_manager : MonoBehaviour {
public GameObject Basket;
private float x_value;
private float y_value;
public GameObject ball;
private ball_script basketBallScript;
private bool dunkCompleteOperation;
// Use this for initialization
void Start () {
Vector2 randomVector = new Vector2(Random.Range(-9f, 9f), Random.Range(0f, 3f));
Debug.Log(randomVector);
Instantiate(Basket, randomVector, transform.rotation);
// Get the ref. to ballObj, which is instantiated. Then assign the script.
GameObject ballObj = Instantiate(ball, new Vector2(0, -3.5f),
transform.rotation) as GameObject;
basketBallScript = ballObj.GetComponent<ball_script>();
}
// Update is called once per frame
void Update () {
dunkCompleteOperation = basketBallScript.dunkComplete;
if (dunkCompleteOperation == true)
{
Vector2 randomVector = new Vector2(Random.Range(-9f, 9f), Random.Range(0f, 3f));
Instantiate(Basket, randomVector, transform.rotation);
}
}
}
Also, just for making your code easier to follow to the others in the future, you might want to check out the general naming conventions.
i'm new to unity and i'm trying to make an endless runner. When my player (a ball) hits one of the walls the game needs to go the scene: LostMenu. My problem is that the collision doesn't work. Nothing happens when they collide... Here are the inspectors on both the player and the walls: Walls http://prntscr.com/a2pgzm Player http://prntscr.com/a2ph66 .
The collision script on the walls:
using UnityEngine;
using System.Collections;
public class LostByWallCSR : MonoBehaviour
{
void OnCollisionEnter (Collision col)
{
if(col.gameObject.name == "Player")
{
Application.LoadLevel("LostMenu");
Debug.Log ("WORKS!");
}
}
}
The movement script on the player:
using UnityEngine;
using System.Collections;
public class CharacterControllerz : MonoBehaviour {
public float speed = 5f;
public float gravity = 20f;
private Vector3 moveDirections = new Vector3();
private Vector3 inputs = new Vector3();
void FixedUpdate()
{
CharacterController cc = GetComponent<CharacterController>();
if (cc.isGrounded)
{
if (Input.GetKey("left"))
inputs.z = 3;
else if (Input.GetKey("right"))
inputs.z = -3;
else
inputs.z = 0;
moveDirections = transform.TransformDirection(inputs.x, 0, inputs.z) * speed;
}
inputs.x = 5;
moveDirections.y = inputs.y - gravity;
cc.Move(moveDirections * Time.deltaTime);
}
}
Any idea on how to setup the collision properly? Attaching a rigibody is not helping it. Unless i'm missing something ofcourse.
Make sure both objects have a collider component.
You need to attach a rigidbody component to one of the objects.(if you don't attach rigid body it will not work)
your Sphere collider is Trigger , remove that or change your function to
public void OnTriggerEnter(Collider other)
{
}
You need to use OnControllerColliderHit method
private void OnControllerColliderHit(ControllerColliderHit hit)
{
if (hit.gameObject.CompareTag("Trap"))
{
Debug.Log("colisiono with trap");
playerDentro = true;
}
else
{
if (!hit.gameObject.CompareTag("Trap"))
{
Debug.Log("player salio de la trampa");
playerDentro = false;
}
}
}e