I'm having an issue with Unity Trail Renderer. I'm expecting trail to appear only when moving finger, but instead I also get straight line connecting the end of last trail to the beginning of a new one. Is this a visual bug in simulation or expected result of my code?
First of all, I have Weapon object with corresponding script Weapon.cs, where the position of rigidbody of said object is dictated by touch.position:
public class Weapon : MonoBehaviour
{
private Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Moved)
{
rb.position = Camera.main.ScreenToWorldPoint(touch.position);
}
}
}
}
Then I have Trail Renderer Component on the Blade which is a child object of Weapon. In Blade.cs I use Trail.Clear() to remove all existing points of TrailRenderer when user ends Touch. I checked the size of trail array on Touch.Began but it was empty as expected so there is no reason for TrailRenderer to connect these points. I also tried to play around with Trail.emit but the result was the same.
Here's the Blade.cs script:
public class Blade : MonoBehaviour
{
private TrailRenderer tr;
void Start()
{
tr = GetComponent<TrailRenderer>();
}
void Update()
{
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Ended)
{
tr.Clear();
}
}
}
}
Here's the result:
Also, worth mentioning that I am using Simulated Touchscreen from com.unity.inputsystem.
Thanks in advance!
Related
hey guys I am trying to destroy a specific object coming towards me when touch it just like guitar hero.
my code right now just destroy wherever I touch
I am new to coding so I appreciate a basic explanations thx you
{
private float forcemult = 200;
private Rigidbody rb;
Ray ray;
RaycastHit hit;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
rb.AddForce(transform.forward * forcemult * Time.deltaTime);
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
{
ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
}
if (Physics.Raycast(ray, out hit ))
{
Debug.Log("hit something");
Destroy(hit.transform.gameObject);
}
else
{
if (Input.touchCount > 0)
{
Vector2 touchDeltaPosition = Input.GetTouch(0).deltaPosition;
}
}
You can give your gameobject a specific tag and then check if the gameobject you hitted has this tag.
Something like:
if(hit.collider.tag == "Enemy") {
// Do Stuff
}
This is the simplest way to check for a collision with a specific gameobject.
You can also check if the name of the gameobject you hitted has the name you want for example:
if(hit.collider.gameobject.name == "Enemy01") {
// Do Stuff
}
I personally don't like the name checking variant, because it only works reliably in specific situations.
Another method you can use is attaching a script to the gameobject and then check if the gameobject has this script:
YourScript script = hit.collider.gameobject.GetComponent<YourScript>();
if(script != null) {
// Do stuff
}
This is probably the best way of handling this because you can instantly call an event after the collision happened.
The part of the code that is responisble for detecting objects is if (Physics.Raycast(ray, out hit )). You can add two additional inputs to this method to destory the objects you desire. The first input is maxDistance which is the max distance the ray should check for collisions, the second one is layerMask which is a Layer mask that is used to selectively ignore colliders when casting a ray.
Define a new layer in unity and assign it to the objects you wish to desotry.
click on edit layers:
Define a serialized field of type layerMask and assign the layer (Target in my case) you defined in the inspector:
// assign in the inspector
[SerializeField] private LayerMask toHit;
// your code
//..
// you can define the hit variable in the if statement if you
// don't need it somewhere else using the syntax I have used,
// otherwise remove the var keyword, the 100 is the maxDistance value,
// use any value you wish. toHit determines what physic engine selects
// and what ingores.
if(Physics.Raycast(ray, out var hit, 100, toHit))
{
Debug.Log($"hit: {hit.transform.name}");
Destroy(hit.transform.gameObject);
}
(Unity Doc)
I'm new to Unity so this can be an amateur mistake.
I'm trying to create a simple game that moves a simple sprite circle to a random position upon receiving touch input.
the program works well in Scene tab, but the circle fully disappears in game tab and the connected remote device after receiving touch input.
Here's the script I have connected to my sprite circle Object :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Main : MonoBehaviour
{
private Touch theTouch;
private Camera cam;
// Start is called before the first frame update
void Start()
{
cam = Camera.main;
}
// Update is called once per frame
void Update()
{
if (Input.touchCount > 0)
{
theTouch = Input.GetTouch(0);
if (theTouch.phase == TouchPhase.Ended)
{
MoveToRandomePosition();
}
}
}
// Random Movement
void MoveToRandomePosition()
{
var position = cam.ScreenToWorldPoint(new Vector2(Random.Range(0, Screen.width), Random.Range(0, Screen.height)));
transform.position = position;
}
}
You may wanna check the Z coord of your camera and circle. If you're spawning it behind the camera, it wont render.
You could do something like position.z = 0 if your cam pos is at the default -10.
I have a moving platform in a 2D Sidescroller built in Unity 2020.1
The Moving Platform translates between two points using the MoveTo method. It does not have a RigidBody2D component.
I attach the Player to the platform by making it the child of the platform using OnCollisionEnter2D and OnCollisionExit2D to parent the Player to the parent and reset to null respectively. Works great.
I'm using the CharacterController from Standard Assets.
The problem:
The player just walks in place when I try to move him back and forth on the platform.
What I've tried so far:
Changing the current velocity of the player by adding a constant to the x dimension of it's move vector.
Works kinda sorta but that constant needs to be huge to get it to move even a little bit. It's a huge kluge that violates every sense of coding propriety.
Put a RigidBody2D on the platform. Make it kinematic so it doesn't fall to the ground when I land on it. Move the platform via "rb.velocity = new Vector2(speed, rb.velocity.y)";
2a) Attempt to make the Player a child of the kinematic platform.
Player is made a child, but it doesn't move with the platform as expected. I believe that this is because both objects have RigidBody2D components, which I gather don't play well together based on what I've read.
2b) Attempt to add the platform's moving vector to the player's movement vector to make him stay in one place. Player stays stationary to make sure he stays fixed on the platform.
No dice.
I'm all out of ideas. Perusing videos on making player's stick to moving platforms all use the platform to move the player from place to place, without expecting that the game may want the player to move back and forth on the platform as the platform is moving.
I can't believe that this isn't a solved problem, but my Google foo isn't getting me any answers.
Thanks.
I'm a fairly newbie to Unity and C# but I wanted to help so I tried simulating your game for a solution and I didn't run into any problems using this script as the Player movement (you can modify variables as u like, add a separate variable for jump speed to make it smoother etc)
public class Player : MonoBehaviour {
Rigidbody2D rb;
float speed = 7f;
Vector3 movement;
public bool isOnGround;
public bool isOnPlatform;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
movement = new Vector3(Input.GetAxis("Horizontal"), 0f, 0f);
transform.position += movement * speed * Time.deltaTime;
Jump();
}
void Jump()
{
if (Input.GetButtonDown("Jump") && isOnGround || Input.GetButtonDown("Jump") && isOnPlatform)
{
rb.AddForce(transform.up * speed, ForceMode2D.Impulse);
}
}
}
Also add an empty child object to your Player gameObject and add a BoxCollider2D at his feet, narrow it down on Y axis like this
also attach this script to that child gameObject to check if player is on the ground(tag ground collider objects with new tag "Ground") so u don't jump infinitely while in the air OR if the player is on the platform(tag platform collider objects with "Platform") so you're still able to jump off it
public class GroundCheck : MonoBehaviour {
Player player;
MovingPlatform mp;
// Start is called before the first frame update
void Start()
{
player = FindObjectOfType<Player>();
mp = FindObjectOfType<MovingPlatform>();
}
private void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.tag == "Ground")
{
player.isOnGround = true;
}
if (other.gameObject.tag == "Platform")
{
player.isOnPlatform = true;
transform.parent.SetParent(other.transform);
mp.MoveThePlatform();
}
}
private void OnCollisionExit2D(Collision2D other)
{
if (other.gameObject.tag == "Ground")
{
player.isOnGround = false;
}
if (other.gameObject.tag == "Platform")
{
transform.parent.SetParent(null);
}
}
}
and finally for platform movement (no RigidBody2Ds, just a collider)
public class MovingPlatform : MonoBehaviour {
bool moving;
public Transform moveHere;
// Update is called once per frame
void Update()
{
if (moving)
{
gameObject.transform.position = Vector2.MoveTowards(transform.position, moveHere.position, 2f * Time.deltaTime);
}
}
public void MoveThePlatform()
{
moving = true;
}
}
additional images
Player, Platform
P.s. Forgot to add - on Player's RigidBody2D, under Constraints, check the "Freeze Rotation Z" box.
I'm trying to make my character do a drop attack in Unity where I want to ignore the collision detection of boxCollider2D for the moment when character & an enemy collide, then undo the ignore. So far the ignore collision is working but it's not reverting back to detect. So after the first successful drop attack my character can pass through the enemy instead of colliding. Here's my code below,
private Rigidbody2D rb;
private Animator anm;
private Collider2D coll;
private enum State {idle, running, jumping, attacking, falling, hurt}
private void OnCollisionEnter2D(Collision2D other) {
if (other.gameObject.tag == "Enemy") {
Enemy enemy = other.gameObject.GetComponent<Enemy>();
if (state == State.falling && anm.GetBool("dropAtk")) { // hurt enemy if drop attack
enemy.Hurt();
Physics2D.IgnoreCollision(other.gameObject.GetComponent<Collider2D>(), GetComponent<Collider2D>(), true);
} else { // take damange
if (other.gameObject.transform.position.x > transform.position.x) {
PlayerHurt("right");
} else {
PlayerHurt("left");
}
}
}
}
private void OnCollisionExit2D(Collision2D other) {
if (other.gameObject.tag == "Enemy") {
if (coll.IsTouchingLayers(ground)) {
Physics2D.IgnoreCollision(other.gameObject.GetComponent<Collider2D>(), GetComponent<Collider2D>(), false);
}
}
}
How can I re-enable collision detection by turning off the IgnoreCollision when character hits the ground? I'm a novice in unity so any suggestion will be really helpful. Thank you!
hope you get the idea
// Update is called once per frame
void FixedUpdate()
{
if(state==dropattck)
{
ChangeTrigger(player, true);
if(player.transform.position.y<floorvalue/*check your floor value*/)
{
transform.position.y = floorvalue;
}
}else
{
ChangeTrigger(player, false);
}
}
public void ChangeTrigger(GameObject obj,bool tf)
{
if(obj.GetComponent<Collider2D>().isTrigger!=tf)
obj.GetComponent<Collider2D>().isTrigger = tf;
}
a solution that comes to mind is to bound the position on the y axis and then temporarily set your collider to trigger. you bound the y so the player doesn't fall through the floor
otherwise you can check when your animation ends and set the collider back to detecting
I have this C# script attached to my main camera game object which also has a capsule collider attribute. However, it doesn't seem to do anything. How should I modify/add to this to make the camera "jump" and fall down to the ground again?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Jump : MonoBehaviour {
[HideInInspector] public bool jump = false;
public float jumpForce = 1000f;
public Transform groundCheck;
private bool grounded = false;
private Rigidbody rb;
// Use this for initialization
void Awake ()
{
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update ()
{
grounded = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground"));
if (Input.GetButtonDown("Jump") && grounded)
{
jump = true;
}
}
void FixedUpdate()
{
if (jump)
{
rb.AddForce(new Vector2(0f, jumpForce));
jump = false;
}
}
}
Also, I would like to have the key for this be the spacebar if possible, but whatever key works or is there already is fine. I am still learning C#, so please forgive me if the solution is obvious.
This line is most likely causing the problem:
grounded = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground"));`
There are 2 reason that it wont produce proper results:
You haven't setup your ground tiles or the place where you character moves to the "Ground" layer. You wont have this by default but you can add it from the Project Settings->Tags and Layers menu.
Your colliders are not close enough to the ground thus not causing collision.
Besides that it should work fine.