I made a replica project to the game Knife Hit. And I'm having trouble with the following question, is my knife hitting the target before it hits it, or the target is detecting the hit before the knife even arrives. What causes the knife to fly around the target, where it should be stuck on the target. As shown in the image below. Consequently, the spawn of the knives that stay on the target, which is to hinder the gameplay, happen the same, are born and are flying around the target.
The code i use is this:
void Update()
{
if (shoot)
{
lastPosition = transform.position;
transform.position += Vector3.up * speed * Time.deltaTime;
RaycastHit2D hit = Physics2D.Linecast(lastPosition, transform.position);
if(hit.collider != null)
{
shoot = false;
if (hit.transform.tag == "Knife")
{
Level.Instance.HitWrong();
rigidbody.bodyType = RigidbodyType2D.Dynamic;
rigidbody.AddTorque(10, ForceMode2D.Impulse);
}
else
{
transform.position = new Vector3(transform.position.x, hit.point.y, transform.position.y);
transform.parent = hit.transform;
collider.enabled = true;
Level.Instance.HitSucced(rigidbody);
}
}
}
}
You need to make sure your 2D colliders are properly "cutout" outlined... My guess is that your 2D collider is really big around the knife or target
Related
I create raycast2d script on my game for the HandGun and that works well when the near enemy on distance, taking damage to the enemy.
if (getShop.isPistol)
{
directionShoot = transform.up;
RaycastHit2D hit = Physics2D.Raycast(transform.position, directionShoot, shootDist, mask.value);
if (hit.collider != null)
{
Debug.DrawLine(transform.position, hit.point, Color.green);
hit.collider.gameObject.SendMessage("Damaged", damageTaken);
}
else
{
Debug.DrawLine(transform.position, directionShoot, Color.red);
}
GameObject bullet = Instantiate(bulletPrefab[0], firePoint[0].position, firePoint[0].rotation);
Bullet bulletScript = bullet.GetComponent<Bullet>();
bulletScript.velocity = firePoint[0].up * bulletForce * 10;
bulletScript.player = gameObject;
Destroy(bullet, 2f);
}
else if (getShop.isShotgun)
{
the shotgun
}
and for the shotgun, I recently use same as the Handgun instantiating one by one but I don't want to that so my question is can I use multiple raycast2d without raycastAll on the shotgun and how to add a spread bullet on it in topdown.
If your question is "can i make multiple raycasts per frame" the answer is yes, you can.
You would do something like
List<RaycastHit2D> hits = new List<RaycastHit2D>();
for(int i = 0; i < numberOfBulletsInShotgunShot; i++){
// modify your direction by some small amount here
RaycastHit2D hit = Physics2D.Raycast(transform.position, directionShoot, shootDist, mask.value);
if (hit.collider != null){
hits.Add(hit); // add hits to your list
}
}
// loop through deal with your hits here
Altering the direction slightly to spread your bullets out
I make a 2d game in unity, and I need your help.
Example
.
The game is that randomly create 9 colored dots as shown in the picture.
The player must connect the dots with the corresponding color. All this I did.
Problem:
As soon as I click on one dot and move immediately to another for connect, it does not connect immediately, but after about 1 second.
If I click on one point and hold about 1 second, and then quickly move to the next point, it connects.
That is, I need to either wait for the first point, or for the second.
As it turns out, all this is because of colliders and Raycast.
He does not have time for check.
Example of my code (very shortened):
Vector3 startPos;
Vector3 endPos;
Vector3 mousePos;
Vector2 mousePos2D;
RaycastHit2D hit;
void Update() {
mousePos = Camera.main.ScreenToWorldPoint (Input.mousePosition);
mousePos2D = new Vector2 (mousePos.x, mousePos.y);
hit = Physics2D.Raycast (mousePos2D, Vector2.zero);
// Here comes the creation of the first point and the connection
if (Input.GetMouseDown(0)) {
if (hit.collider != null) {
color = hit.collider.tag;
startPos = hit.collider.transform.position;
endPos = mousePos2D;
}
}
// Here comes the creation line between dots
if (Input.GetMouse(0)) {
if (hit.collider != null) {
if (hit.collider.tag == color) {
endPos = hit.collider.transform.position;
// Here is instantiated new line and with startPos and endPos and I set
startPos = endPos;
endPos = mousePos2D;
}
}
}
// Here points are deleted if connected
if (Input.GetMouseUp(0)) {
// Nothing important
}
}
The problem is that: in "Input.GetMouseDown(0)", even if the mouse passes through the object "hit.collider is equal null", and after about 1 sec, hit.collider is not null and give the color tag.
Video example:
https://www.youtube.com/watch?v=8x6TSBfBIzc
All code script:
https://drive.google.com/open?id=1QKRInr26acu-E4zXPUf-DbW0h9zbsnUr
How to solve this problem with expectation? Why it does not connect immediately?
I'm using Windows 7 Ultimate (SP1),
Unity 5.3.2 (also tested with 5.3.0, 5.3.1, 5.2.4).
I've caused a bug which is visible in editor, standalone builds, Android builds.
Simple sceene contains:
Sphere - GameObject without sphere colider and with Rigidbody2D which is used by movement script:
private Rigidbody2D m_rigidbody;
void Start() {
m_rigidbody = GetComponent<Rigidbody2D>();
}
void Update() {
if (Input.GetAxis("Horizontal") > 0) //RIGHT
{
m_rigidbody.velocity = new Vector2(1, 0);
} else if (Input.GetAxis("Horizontal") < 0) //LEFT
{
m_rigidbody.velocity = new Vector2(-1, 0);
}
else
{
m_rigidbody.velocity = new Vector2(0, 0);
}
}
3 Cubes - static GameObjects (for abillity to see that sphere is moving)
MainCamera - classic camera, that follows shere using CS script:
public Transform m_Target;
void Update () {
transform.position = Vector3.Lerp(transform.position, new Vector3(m_Target.position.x, transform.position.y, transform.position.z), 1f);
}
Problem: while camera moves, we can see, that (static) GameObjects are "twitching" on the screen...
I've used FixedUpdate in scripts(didn't solve the problem).
Used different Interpolate settings: even used on both (sphere and camera) kinematic Rigidbody2D Extrapolate setting (didn't solve the problem).
Tried to use Rigidbody (instead os Rigidbody2D).
I've found similar question Link to unity3d.ru forum
(didn't solve the problem)
Update: I've set a movement script to Camera and turned off "camera follow". Just simple standart camera moving right (or left) with constant speed and result - static objects are twitching...
In your code,
transform.position = Vector3.Lerp(transform.position, new Vector3(m_Target.position.x, transform.position.y, transform.position.z), 1f);
...your interpolant factor is 1f. That would just make it jump directly to the target value rather than lerping it. I suggest changing that to something else, like 0.75f. That is,
transform.position = Vector3.Lerp(transform.position, new Vector3(m_Target.position.x, transform.position.y, transform.position.z), 0.75f);
I hope that helps!
I have a issue with my 2D game in unity (pokemon style), I'm using transform.position to move the gameobjects.
I have a player and enemies that follow him, all is ok. But when the enemies make a collision, they begin to push each other
I need that nobody to be pushed when the enemies and player get a collision.
I tried to use kinematic in enemies, but the player can push them.
I tried to add a big amount of mass to the player, but he can push the enemies.
I tried to detect the collision in code with OnCollision, but when I cancel the enemy movement, they don't return to move.
----UPDATE----
I need the collision but without pushing between them, here is a video to illustrate the problem
https://www.youtube.com/watch?v=VkgnV1NOxlw
Just for the record, i'm using A* pathfinding script (http://arongranberg.com/astar/) here my enemies move script.
void FixedUpdate () {
if(path == null)
return;
if(currentWayPoint >= path.vectorPath.Count)
return;
Vector3 wayPoint = path.vectorPath [currentWayPoint];
wayPoint.z = transform.position.z;
transform.position = Vector3.MoveTowards (transform.position, wayPoint, Time.deltaTime * speed);
float distance = Vector3.Distance (transform.position, wayPoint);
if(distance == 0){
currentWayPoint++;
}
}
----UPDATE----
Finally I'll get the expected result,changing the rigidbody2D.isKinematic property to true when the target was close and stop it
Here is a video https://www.youtube.com/watch?v=0Zm0idUU75s
And the enemy movement code
void FixedUpdate () {
if(path == null)
return;
if(currentWayPoint >= path.vectorPath.Count)
return;
float distanceTarget = Vector3.Distance (transform.position, target.position);
if (distanceTarget <= 1.5f) {
rigidbody2D.isKinematic = true;
return;
}else{
rigidbody2D.isKinematic = false;
}
Vector3 wayPoint = path.vectorPath [currentWayPoint];
wayPoint.z = transform.position.z;
transform.position = Vector3.MoveTowards (transform.position, wayPoint, Time.deltaTime * speed);
float distance = Vector3.Distance (transform.position, wayPoint);
if(distance == 0){
currentWayPoint++;
}
}
You can do this in several ways,
You can use Physics2D.IgnoreCollision
Physics2D.IgnoreCollision(someGameObject.collider2D, collider2D);
Make sure that you do the IgnoreCollision call before the collision occurs, maybe when objects instantiate.
or alternatively you can use, Layer Collision Matrix
Unity Manual provides information on using this. This simply does the collision avoidance by assigning different GameObjects to different layers. Try:
Edit->Project Settings->Physics
Or if you want it to just stop moving, You can easily do it like,
bool isCollided = false;
// when when OnCollisionEnter() is called stop moving.
//maybe write your move script like
void Move() {
if(!isCollided) {
// move logic
}
}
I have an object called 'Player' in my scene.
I also have multiple objects called 'Trees'.
Now I'd like whenever the user clicks on a 'Tree', the 'Player' to move slowly to that position (using Lerp or moveTowards) is both O.K for me.
Now I have 2 issues with this code:
I'd like this code to be generic
Whenever I click a tree object I'd like this to move the player towards that tree. I don't want to write up this script and attach it to each tree object.
Where should I put the script?
Currently I attach this code to every tree object.
How should I write it down so that it applies to every tree object
in the scene?
If another click is made while moving, cancel previous movement and start moving to new position
How should I write it so that if I click on another object while the
player is moving towards another object that was clicked, the players stops moving towards it's previous position, and starts
moving towards the new point.
I'm having some trouble adjusting to the new UnityScript thingy. I come strictly from a Javascript background and it really seems like the 2 of them are languages with very different semantics. So if someone answers this with code(which is what I would want:) ), I'd appreciate some verbose comments as well.
I currently do this:
var playerIsMoving = false;
Public playerObject: Gameobject; //I drag in the editor the player in this public var
function update(){
var thisTreePosition = transform.point; //this store the X pos of the tree
var playerPosition = player.transform.point;
if(playerIsMoving){
player.transform.position = Vector2.MoveTowards(playerPosition, thisTreePosition, step);
}
}
function OnMouseDown(){
playerIsMoving = true;
}
I'm writing this from home where I don't have Unity and I forgot the code syntax therefore expect the above code to have typos or issues, at work it works just fine, apart from being very crude and unsophisticated.
I would recommend you to put the movement Script on the player. And how abour using Raycast to the test whether you hit a tree?
http://docs.unity3d.com/ScriptReference/Physics.Raycast.html
Vector3 positionToWalkTo = new Vector3();
void Update() {
if (Input.GetMouseButtonDown(0)) {
RaycastHit hit;
Ray ray = new Ray(transform.position, direction);
if (Physics.Raycast(ray, out hit))
if (hit.gameObject.tag.Equals("tree")){
positionToWalkTo = hit.gameObject.transform.position;
}
}
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, positionToWalkTo, step);
}
To get something like this running, you should tag all the trees.
'JavaScript'
var target: Transform;
// Speed in units per sec.
var speed: float;
function Update () {
if (Input.GetMouseButtonDown(0)) {
var hit: RaycastHit;
var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
// Raycasting is like shooting something into the given direction (ray) and hit is the object which got hit
if (Physics.Raycast(ray, hit)) {
if (hit.gameObject.tag = "tree")
target = hit.gameObject.transform.position; // Sets the new target position
}
}
// The step size is equal to speed times frame time.
var step = speed * Time.deltaTime;
// Move our position a step closer to the target.
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
}
Okay, so I've done it myself (with some help from Freshchris's answer).
Here it is:
var target:Vector2;
var targetObject:GameObject;
var initialY:float;
var tolerance = 1;
var speed = 3;
var isMoving = false;
function Start(){
target = transform.position;
}
function Update () {
if (Input.GetMouseButtonDown(0)) {
var hit: RaycastHit2D = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero); //raycast the scene
// if we hit something
if (hit.collider != null) {
isMoving=true; //it should start moving
targetObject = hit.collider.gameObject; //the target object
target = hit.collider.gameObject.transform.position;
}
}
// The step size is equal to speed times frame time.
var step = speed * Time.deltaTime;
// if it should be moving - move it - and face the player to the correct direction
if (isMoving){
if(transform.position.x>target.x){
gameObject.transform.localScale.x = -0.7;
}else {
gameObject.transform.localScale.x = 0.7;
}
transform.position = Vector2.MoveTowards(transform.position, target, step);
}
// if it reached the target object by a specified tolerance, tell it to stop moving
if(isMoving){
if((transform.position.x < target.x+tolerance)&&(transform.position.x > target.x-tolerance)){
print("position reached"); //this is fired just once since isMoving is switched to false just one line below
print(targetObject);
isMoving=false;
}
}
}