Search Unity

Help with bat and ball type physics.

Discussion in 'Physics' started by Shabbalaka, Nov 28, 2019.

  1. Shabbalaka

    Shabbalaka

    Joined:
    Jan 15, 2018
    Posts:
    112
    Hi I am creating a puck like game where there is 2 players each player has their own paddle and a puckj which goes up and down the table much like the air hockey game you see in arcades sometimes.

    I have all the functionality working except I am finding that when I drag the paddle and "hit" the ball / puck with it it rolls about the speed of a snail.

    Whats the best way to simulate a ball hit and also like if i hit the ball with the corner of the paddle it would obviously send the ball off in a direction rather than in a straight line.

    I am guessing its some kind of angular trajectory which can be processed.

    The players paddle is a Rigidbody with a Box Collider which is Kinematic.
    The puck is a Dynamic Sphere collirde with a rigidbody.

    I am wondering do i need to cast a ray from the poitn of contact and then use AddForce to create the effect of "hitting" the puck with the paddle.

    So in short I have 2 issues here.

    1: The physics of the ball not being accurate
    2 : Determining the trajectory of the ball and then basing the force of the ball by the speed at which the paddle hit it.
    3 :The paddle can move back and forward (This can be considered a "force meter" like "How fast i got from near to far is the "force" applied to the puck.

    *Update : Just thought I could add some more information, To better see what I am talking about there is a game called Shufflepuck Cafe that my partner used to play as a child and I am trying to recreate it so she can play it on her mobile. ;D

    As stated I have all the paddles moving and collision detections are working its just being able to "hit" th ball/puck which is trying me, I have looked around at several examples and none of them are any good!!

    Please help this is driving me crazy XD

    Sorry if this isnt very clear but I am not sure how much better to explain it.

    Any suggestions or links to guides is appreciated!

    thanks!
     
    Last edited: Nov 29, 2019
  2. devotid

    devotid

    Joined:
    Nov 14, 2011
    Posts:
    373
    Make sure the scale is real world. If the pucks are moving really slowly My guess is they are huge.

    Create a new cube and make sure it is 1,1,1. The puck should be tiny compared to a 1 meter cube.
     
  3. Shabbalaka

    Shabbalaka

    Joined:
    Jan 15, 2018
    Posts:
    112
    I just chedked the scale of the paddle and the scale of the ball and both are set to 0.2 on the x,y,z, I will have ot scale it all up now :).

    I will do that and get back to you!


    Many thanks for the reply really appreciated!

    Ok just resized a lot of the things

    Table scale -= 40, 150, 75
    Paddle scale = 75,20,20
    Ball / Puck scale = 10,10,10 (Rigidbody, Mass Drag, Angular Drag and Mass all set to 0, Use GRavity is checked.

    The ball still moves as slow as a snail even if i put the ball at a scale of 1,1,1 (Which results in the ball being the size of a pixel it still doesnt move when i hit with the paddle.

    I am assuming they "faked" a hit force in shufflepuck cafe by calculating how fast it took the player to move the paddle from their current position to the point of impact and then used that to addforce to the puck.

    Its the only thing i can think of at the moment : (

    I have uploaded the package file if you are able to look at it, I would appreciate it a tonne.

    Once again thanks for the reply!
     

    Attached Files:

    Last edited: Nov 30, 2019
  4. devotid

    devotid

    Joined:
    Nov 14, 2011
    Posts:
    373
    Ok I open the scene and created a little scene similar to yours but its the proper scale and I also added Physics materials for you. Make sure to hit play a few times and play with the physics materials on different angles and shapes. You will see the slight angle of the table will make the balls roll proper.

    You WILL NEVER achieve real physics with items that are not real life scale. I also put a 6 foot male standing next to the table to give you an idea of scale. The balls on the table are about the size of a real life baseball. Your ball in the original scene was the size of Rhode Island. Get why it moves pretty slowly now? Your camera was about a kilometer away. If the ball was covering the span of the camera it would have to be moving faster than a comet through space. ;)

    I dont have time to make the scripts and stuff but you seem to have that covered. I just wanted to make sure you are on the right page to get a good start.

    Good luck.
     

    Attached Files:

  5. Shabbalaka

    Shabbalaka

    Joined:
    Jan 15, 2018
    Posts:
    112
    Wow!

    Many thanks for the explanation and the scaling demo, This should help quite a lot!

    I did not realise my scaling was so off, I,ve not really looked into the "scale" property too much as i,ve usually said "that looks fine in the camera so it must be good" lol

    I,ll plod on with the project and see if I can complete it ;)

    Once again, Really appreciate the reply!

    Edit : I applied the dragging script to the paddle but it still does not have the effect I am trying to achieve..



    I found this video which is exactly what I am trying to create.
     
    Last edited: Dec 1, 2019
  6. devotid

    devotid

    Joined:
    Nov 14, 2011
    Posts:
    373
    Thats quite and involved bit of code there.... You need to develop a pretty robust "hitting system" for the player and thats not even including the AI thats returning the shot.

    Just start with having a puck first on the table and working on writing code that when you hit the space bar or mouse click it applies a force to the rigidbody of the puck in the direction of the other goal. If you are looking at making a system that you can swipe your mouse and hit the moving puck its going to be much more involved than that script that you have attached.

    Maybe a hinge that you can control the "swing" of the "player arm" with .TargetPosition. THats how I do it in one of my games. Then just make the hinge "swing once" when the player choses a spot and a power level by holding the mouse or something.
     
  7. Shabbalaka

    Shabbalaka

    Joined:
    Jan 15, 2018
    Posts:
    112
    Thanks for the reply,

    I was under the impression the physics system took into account how fast an object was moving compared to the size and mass of it and it would automatically calculate the force required to move the puck for example

    If a 1 tonne car hit a building at 80mph it would most likely destroy the car but not the building
    If a 18 tonne articulated lorry hit a building at 80mph it would most likely destroy the lorry and the building due to the extra force of the lorry,s weight.

    Seems that I will have to calculate this myself, I will take small steps and just do a script that initially will just add force to the puck and then try to add a "aiming" system for the player.

    Thanks again!
     
  8. Shabbalaka

    Shabbalaka

    Joined:
    Jan 15, 2018
    Posts:
    112
    In the meanwhile I wrote this script which calculates the distance travelled and the duration of the drag and then applies that force to Z axis of the object.


    I also wrote the script to add a force to a specific ball.

    I gave each of the material balls a color and then I added them via the inspector

    AddForce.cs
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. public class BallVelocitySpeed : MonoBehaviour
    6. {
    7.  
    8.     public Text txtRedBall;
    9.     public Text txtBlueBall;
    10.     public Text txtGreenBall;
    11.  
    12.  
    13.     public GameObject objRedBall;
    14.     public GameObject objBlueBall;
    15.     public GameObject objGreenBall;
    16.  
    17.     private Rigidbody rbRed;
    18.     private Rigidbody rbBlue;
    19.     private Rigidbody rbGreen;
    20.  
    21.  
    22.  
    23.     // Start is called before the first frame update
    24.     void Start()
    25.     {
    26.         rbRed = objRedBall.GetComponent<Rigidbody>();
    27.         rbBlue =  objBlueBall.GetComponent<Rigidbody>();
    28.         rbGreen = objGreenBall.GetComponent<Rigidbody>();
    29.     }
    30.  
    31.     // Update is called once per frame
    32.     void Update()
    33.     {
    34.       Vector3 redSpeed = rbRed.velocity;
    35.       txtRedBall.text += redSpeed;  
    36.     }
    37. }
    38.  


    ForceOverDistance
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PositionCalculation : MonoBehaviour
    6. {
    7.  
    8.     public Vector3 curPos;
    9.     public Vector3 endPos;
    10.     public float startDrag;
    11.     public float endDrag;
    12.     public float Distance;
    13.     public float DragDuration;
    14.  
    15.     public float forceCalculated;
    16.     public float PrevForceApplied;
    17.  
    18.     // Update is called once per frame
    19.     void Update()
    20.     {
    21.      
    22.         if(Input.GetMouseButtonDown(0))
    23.         {
    24.             curPos = transform.position;
    25.             startDrag = Time.time;
    26.         }
    27.         if(Input.GetMouseButtonUp(0))
    28.         {
    29.             endPos = transform.position;
    30.             endDrag = Time.time;
    31.         }
    32.  
    33.         Distance = CalculateDistanceTravelled(curPos,endPos);
    34.         DragDuration = CalculateDragDuration(startDrag, endDrag);
    35.  
    36.         if(DragDuration > 0f)
    37.         {
    38.             ApplyForceBasedOnDurationAndDistance();
    39.  
    40.         }
    41.  
    42.     }
    43.  
    44.     float CalculateDragDuration(float stime, float etime)
    45.     {
    46.         float duration = etime - stime;
    47.  
    48.         return duration;
    49.     }
    50.  
    51.     float CalculateDistanceTravelled(Vector3 spos, Vector3 epos)
    52.     {
    53.  
    54.         float distance = Vector3.Distance(spos,epos);
    55.      
    56.         return distance;
    57.      
    58.     }
    59.  
    60.     void ApplyForceBasedOnDurationAndDistance()
    61.     {
    62.         Rigidbody rb = GetComponent<Rigidbody>();
    63.  
    64.         forceCalculated = Distance / DragDuration;
    65.         PrevForceApplied = forceCalculated;
    66.  
    67.         rb.AddForce(0,0,forceCalculated);
    68.  
    69.         DragDuration = 0;
    70.         Distance = 0;
    71.         forceCalculated = 0;
    72.  
    73.     }
    74.  
    75. }
    76.  
    DragObject.cs
    Code (CSharp):
    1. using System.Collections;
    2.  
    3. using System.Collections.Generic;
    4.  
    5. using UnityEngine;
    6.  
    7.  
    8.  
    9. public class DragObject : MonoBehaviour
    10.  
    11. {
    12.  
    13.     private Vector3 mOffset;
    14.  
    15.     private float mZCoord;
    16.  
    17.     public float maxX = 2.05f;
    18.     public float minX = -2.05f;
    19.  
    20.     public float minZ = -4.5f;
    21.     public float maxZ = -5.5f;
    22.  
    23.     public float maxHeightFromGround = 0.1f;
    24.  
    25.     void OnMouseDown()
    26.  
    27.     {
    28.  
    29.         mZCoord = Camera.main.WorldToScreenPoint(
    30.  
    31.         gameObject.transform.position).z;
    32.         // Store offset = gameobject world pos - mouse world pos
    33.         mOffset = gameObject.transform.position - GetMouseAsWorldPoint();
    34.     }
    35.  
    36.  
    37.  
    38.     private Vector3 GetMouseAsWorldPoint()
    39.  
    40.     {
    41.         // Pixel coordinates of mouse (x,y)
    42.         Vector3 mousePoint = Input.mousePosition;
    43.         // z coordinate of game object on screen
    44.         mousePoint.z = mZCoord;
    45.         // Convert it to world points
    46.         return Camera.main.ScreenToWorldPoint(mousePoint);
    47.  
    48.     }
    49.  
    50.     private void OnCollisionEnter(Collision other) {
    51.      
    52.              Debug.Log(other.relativeVelocity.magnitude);
    53.             Vector3 collisionForce = other.impulse / Time.fixedDeltaTime;
    54.             Debug.Log(other.impulse);
    55.     }
    56.  
    57.     void OnMouseDrag()
    58.  
    59.     {
    60.       /* LOCKED OUT THE AXIS RESTRICTIONS FOR TESTING PURPOSES.. */
    61.         transform.position = GetMouseAsWorldPoint() + mOffset;
    62.         // if((transform.position.y >= maxHeightFromGround) | (transform.position.y <= maxHeightFromGround))
    63.         // {
    64.         //      Vector3 lockHeight = new Vector3(transform.position.x, maxHeightFromGround , transform.position.z);
    65.         //      transform.position = lockHeight;
    66.  
    67.         //     if(transform.position.x <= minX)
    68.         //     {
    69.              
    70.         //         Vector3 minXLock = new Vector3(minX, maxHeightFromGround, transform.position.z);
    71.         //         transform.position = minXLock;
    72.  
    73.         //     }
    74.         //     if(transform.position.x >= maxX)
    75.         //     {
    76.              
    77.         //         Vector3 maxZLock = new Vector3(maxX, maxHeightFromGround, transform.position.z);
    78.         //         transform.position = maxZLock;
    79.  
    80.         //     }
    81.  
    82.         //       if(transform.position.z >= minZ)
    83.         //     {
    84.              
    85.         //         Vector3 minZLock = new Vector3(transform.position.x, maxHeightFromGround,minZ);
    86.         //         transform.position = minZLock;
    87.  
    88.         //     }
    89.         //     if(transform.position.z <= maxZ)
    90.         //     {
    91.              
    92.         //         Vector3 maxZLock = new Vector3(transform.position.x, maxHeightFromGround, maxZ);
    93.         //         transform.position = maxZLock;
    94.         //         //isBackAsFarAsAllowed = true;
    95.  
    96.         //     }
    97.         // }
    98.     }
    99. }
    Now that we can drag the paddle and get the information of how long its been dragged and how far it has travelled maybe can apply the force to the puck if we collide with it.

    Or am I overcomplicating this? XD
     
    Last edited: Dec 1, 2019
  9. devotid

    devotid

    Joined:
    Nov 14, 2011
    Posts:
    373
    Maybe just setup a "arm" that will make a "swing" at the incoming puck and then just aim the arm left and right with the Horizontal Axis of the mouse. Then just set a start and end pos (or rotation) and interpolate from the start position to the end position. When the arm finishes the swing... just reset the position and swing again. This way you could chop at it just like in real life and add a little "english" to the puck.

    Building a click and drag version might be a bit overboard.... But I use playmaker so I like to stick to very simple and not overthink it. lol.
     
  10. Shabbalaka

    Shabbalaka

    Joined:
    Jan 15, 2018
    Posts:
    112
    Omg.... I was wayyyy overthinking this scenario and all I needed in the end was the following,


    Code (CSharp):
    1.            
    2. if(other.gameObject.tag == "Puck")
    3.             {
    4.                 Rigidbody rb = other.gameObject.GetComponent<Rigidbody>();
    5.                 rb.AddForce(0,0,ForceAmount, ForceMode.Force);
    6.  
    7.             }
    8.            
    This works exactly as I wanted it to the only thing I need now is to adjust the direction slightly as shown in the picture below as if I apply force to it and there is nothing for it to hit it will forever go back and forward, So I would like to add a little control to the player by adjusting the angle of the ball depending on where it hits the paddle, I guess this is possible by checking the point of impact on the paddle and then seeing if its further left or right and then adding that amount of force to the balls X axis either negatively or positively to send it left or right. (Thinking out loud here)

    Many thanks for the replys!
     

    Attached Files: