My variable changes after my gameobject moves, when there is no input to change the variable - unity3d

I'm trying to get the last position of my gameobject, before it stops moving, but the "lastPos" variable keeps being magically changed to the current position, after my gameobject moves. (I'm probs being stupid)
The reason I'm doing this is to try to add smoothing to the end of the movement of my gameobject, instead of stopping suddenly after it being let go, I want it to gradually slide to a stop. So I was thinking if I found the difference between last position before it stops and the current one, I could add some velocity to the end of it, depending on the distance between the two points, the more velocity it would add.
I couldn't find a tutorial on how to add this.
The problem is probably in the last 3 If statements.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move : MonoBehaviour
{
bool dragging = false;
Vector2 offset;
Transform toDrag;
Transform lastPos;
float posDif;
private void Start()
{
Application.targetFrameRate = 60;
}
void Update()
{
Vector2 v2;
if(Input.touchCount != 1)
{
dragging = false;
return;
}
Touch touch = Input.touches[0];
Vector2 pos = touch.position;
if(touch.phase == TouchPhase.Began)
{
toDrag = gameObject.transform;
v2 = new Vector2(pos.x, pos.y);
v2 = Camera.main.ScreenToWorldPoint(v2);
offset.x = toDrag.position.x - v2.x; offset.y = toDrag.position.y - v2.y;
dragging = true;
Debug.Log("TOUCH");
}
if (dragging && touch.phase == TouchPhase.Moved)
{
if (touch.phase != TouchPhase.Stationary && touch.phase != TouchPhase.Ended && touch.phase != TouchPhase.Canceled)
{
lastPos = gameObject.transform;
}
v2 = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
v2 = Camera.main.ScreenToWorldPoint(v2);
toDrag.position = v2 + offset;
gameObject.transform.position = new Vector2(v2.x + offset.x, -2.67f);
Debug.Log("Last Pos: " + lastPos.position.x);
}
if (dragging && (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled))
{
dragging = false;
posDif = gameObject.transform.position.x - lastPos.position.x;
gameObject.GetComponent<Rigidbody2D>().velocity = new Vector2(posDif * 10f, 0f);
Debug.Log("Current Pos: " + gameObject.transform.position.x);
Debug.Log(posDif);
}
}
}

Your lastPos is set to your current gameObject transform. It’s a class, so a reference object, so you’ll always have the latest values.
If you change the type of the lastPos variable to be a Vector3 you’ll be storing that value, at the time you record it. transform.position is a Vector3 which is a struct (a value type).
...
private Vector3 lastPos;
...
if (dragging && touch.phase == TouchPhase.Moved)
{
lastPos = gameObject.transform.position;
v2 = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
v2 = Camera.main.ScreenToWorldPoint(v2);
toDrag.position = v2 + offset;
gameObject.transform.position = new Vector2(v2.x + offset.x, -2.67f);
Debug.Log("Last Pos: " + lastPos);
}
If what I’m talking about sounds alien, here’s the official docs at Microsoft describing the difference between structs (value types) and classes (reference types). Choosing Between Class and Struct

Related

Unity Game BreakOut ball loses speed and direction

I just finished a BreakOut style game but there is a bug where sometimes the ball gets stuck to the edges of the map with no direction or speed as shown in the screenshot
What I see is that it happens when the ball completely loses trajectory or speed, but could not solve the error
enter image description here
my code
public class Ball : MonoBehaviour
{
[SerializeField] Rigidbody2D rigidbody2D;
Vector2 moveDirection;
Vector2 currentVelocity;
float velocity=10;
//GameManager gameManager;
Transform paddle;
[SerializeField] AudioController audioController;
[SerializeField] AudioClip bounceSfx;
[SerializeField] AudioClip dieSfx;
public bool superBall;
[SerializeField] float superBallTime=10;
[SerializeField]float yMinSpeed = 10;
[SerializeField]TrailRenderer trailRenderer;
public bool SuperBall
{
get=> superBall;
set{
superBall=value;
if(superBall)
StartCoroutine(ResetSuperBall());
}
}
// Start is called before the first frame update
void Start()
{
//rigidbody2D = GetComponent<Rigidbody2D>();
//rigidbody2D.velocity = Vector2.up*velocity*Time.deltaTime;
GameManager.Instance = FindObjectOfType<GameManager>();
paddle = transform.parent;
}
// Update is called once per frame
void Update()
{
currentVelocity = rigidbody2D.velocity;
if (Mathf.Abs(currentVelocity.y) < 3 && Mathf.Abs(currentVelocity.y) < 3 && GameManager.Instance.ballOnGame)
{
velocity = 10;
rigidbody2D.velocity = Vector2.up * velocity ;
}
if (Mathf.Abs(currentVelocity.y) + Mathf.Abs(currentVelocity.y) < 10 && GameManager.Instance.ballOnGame)
{
velocity = 10;
rigidbody2D.velocity = Vector2.up * velocity ;
}
if (velocity <10 && GameManager.Instance.ballOnGame)
{
velocity = 10;
rigidbody2D.velocity = Vector2.up * velocity ;
}
if ((Input.GetKey(KeyCode.W) && GameManager.Instance.ballOnGame == false)||(Input.GetKey(KeyCode.Space) && GameManager.Instance.ballOnGame == false))
{
rigidbody2D.velocity = Vector2.up * velocity ;
transform.parent = null;
GameManager.Instance.ballOnGame = true;
rigidbody2D.isKinematic = false;
rigidbody2D.AddForce(new Vector3(velocity, velocity, 0));
if (!GameManager.Instance.GameStarted)
{
GameManager.Instance.GameStarted = true;
}
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.transform.CompareTag("Brick") && superBall)
{
rigidbody2D.velocity = currentVelocity;
return;
}
moveDirection=Vector2.Reflect(currentVelocity,collision.GetContact(0).normal);
if (Mathf.Abs(moveDirection.y) < yMinSpeed)
{
//permitir velocidad minima
moveDirection.y = yMinSpeed*Mathf.Sign(moveDirection.y);
}
rigidbody2D.velocity=moveDirection;
audioController.PlaySfx(bounceSfx);
if (collision.transform.CompareTag("BottomLimit"))
{
if(GameManager.Instance != null)
{
GameManager.Instance.PlayerLives--;
audioController.PlayDie(dieSfx);
if (GameManager.Instance.PlayerLives > 0)
{
rigidbody2D.velocity = Vector2.zero;
transform.SetParent(paddle);
transform.localPosition = new Vector2(0, 0.65f);
GameManager.Instance.ballOnGame = false;
}
}
}
}
IEnumerator ResetSuperBall()
{
trailRenderer.enabled = true;
yield return new WaitForSeconds(superBallTime);
trailRenderer.enabled = false;
GameManager.Instance.powerIsActive = false;
superBall = false;
}
}
This is a common issue with Rigidbodies at low velocities. The physics engine implements a Physics2D.velocityThreshold that is designed to dampen slow bounces and calm down a pile of Rigidbodies.
The default value for velocityThreshold is 1, meaning that the x or y component of the velocity that is slower will be floored to 0.
To resolve this issue you can simply lower the value to 0.001. You can do it in the Physcs2d tab located at Edit->ProjectSettings->Physics2d

Placing Furniture on drag in AR Core

I am new to ARCore in Unity. My colleague has already made this app on iOS. But I am having some problems dragging the object around and set it on a position. Also you can rotate it with 2 fingers. Here I am giving the ARKit equivalent code of m dragging. Can anyone help me with doing the same on AR Core
switch (Input.touchCount) {
case 1:
if (touch.phase == TouchPhase.Began || touch.phase == TouchPhase.Moved) {
var screenPosition = Camera.main.ScreenToViewportPoint(touch.position);
ARPoint point = new ARPoint {
x = screenPosition.x,
y = screenPosition.y
};
// prioritize reults types
ARHitTestResultType[] resultTypes = {
//ARHitTestResultType.ARHitTestResultTypeExistingPlaneUsingExtent,
// if you want to use infinite planes use this:
ARHitTestResultType.ARHitTestResultTypeExistingPlane,
ARHitTestResultType.ARHitTestResultTypeHorizontalPlane,
ARHitTestResultType.ARHitTestResultTypeFeaturePoint
};
foreach (ARHitTestResultType resultType in resultTypes) {
if (HitTestWithResultType(point, resultType)) {
return;
}
}
}
break;
case 2:
if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Ended) {
Vector2 direction = touch.deltaPosition;
float yAngleIncrementVal = touch.deltaPosition.magnitude;
Vector3 currentRotation = transform.rotation.eulerAngles;
if (direction.x > 0) {
currentRotation.y += (yAngleIncrementVal * rotationScale);
}
else {
currentRotation.y -= (yAngleIncrementVal * rotationScale);
}
transform.rotation = Quaternion.Euler(currentRotation);
}
break;
}
}
This script will attached to the gameobject which will move across the plane. How can I drag a gameobject and update the anchors so that it stays on the plane. Thank You
I am pretty much doing the same thing, and this is a simplified version of my own code:
case 1:
if (Input.GetTouch(0).phase == TouchPhase.Began)
{
touchOffset = ARCamera.WorldToScreenPoint(gameObject.position) - new Vector3(Input.GetTouch(0).position.x, Input.GetTouch(0).position.y, 0);
}
RaycastHit hit;
LayerMask layers = (1 << LayerMask.NameToLayer(layersOfGroundObjects))
Ray ray = ARCamera.ScreenPointToRay(Input.GetTouch(0).position + new Vector2(mouseOffset.x, mouseOffset.y));
if (!ClickedOnUI && Physics.Raycast(ray, out hit, Mathf.Infinity, layers))
{
if(Input.GetTouch(0).phase == TouchPhase.Began)
{
touchOffset = hit.point - gameObject.position;
}
if (Input.GetTouch(0).phase == TouchPhase.Moved)
{
gameObject.position = hit.point - touchOffset ;
}
}
case 2:
float currentTouchDistance = Vector2.Distance(touches[0].position, touches[1].position);
float diff_y = touches[0].position.y - touches[1].position.y;
float diff_x = touches[0].position.x - touches[1].position.x;
float currentTouchAngle = Mathf.Atan2(diff_y, diff_x) * Mathf.Rad2Deg;
if (isFirstFrameWithTwoTouches)
{
cachedTouchDistance = currentTouchDistance;
cachedTouchAngle = currentTouchAngle;
isFirstFrameWithTwoTouches = false;
}
float angleDelta = currentTouchAngle - cachedTouchAngle;
float scaleMultiplier = (currentTouchDistance / cachedTouchDistance);
float scaleAmount = cachedAugmentationScale * scaleMultiplier;
float scaleAmountClamped = Mathf.Clamp(scaleAmount, scaleRangeMin, scaleRangeMax);
if (enableRotation)
{
gameObject.localEulerAngles = cachedAugmentationRotation - new Vector3(0, angleDelta * 3f, 0);
}
if (enableRotation && enableScaling)
{
gameObject.localScale = new Vector3(scaleAmountClamped, scaleAmountClamped, scaleAmountClamped);
}
I also use a touchOffset which is the distance away from the object's pivot (position) that the user has clicked to start dragging. I apply that offset to the final position every time it is dragged. It makes dragging feels much more natural. I also use it for a lot more in my own code, therefore it was quite important for me, but that is irrelevant for this question so I removed the rest of the code.
Moreover, I use many layers for what is considered ground, because I can put my furniture on more surfaces other than the ARCore tracked plane. If you only care about the tracked plane then either assign a layer to it, or use ARCore's raycast instead of Unity's one. Or just use my Eazy ARCore Interface plugin that can do both (uses layers for tracked planes and makes things easier with raycasting for multiple surfaces)

Moving object with raycast issues

I have written a script where a gameobject is intended to move to a raycast.point thrown from the player camera. For the most part this works fine, however there are times (approximately when camera is 45 degrees up from the object) when the object rapidly moves towards the camera (i.e. raycast source).
I have tried a number of approaches attempting to resolve this, however I can’t seem to dig out the root of this issue. Managed to prevent this from occurring by deactivating the collider attached to the object being moved. However I need the collider for various reasons so this approach is not appropriate.
If anyone can provide any pointers as to where I am going wrong I would be incredibly grateful.
NB: coding in uJS
Many thanks in advance, Ryan
function FixedUpdate() {
if (modObj != null && !guiMode) {
//Panel Control
if (!selectObjPanel.activeSelf && !modifySelectObjPanel.activeSelf) //if the selectpanel not open and modSelect not already activated
{
activateModSelectObjPanel(true); //activate it
} else if (selectObjPanel.activeSelf) {
activateModSelectObjPanel(false);
}
//Move
if (Input.GetKey(KeyCode.E)) {
if (Input.GetKeyDown(KeyCode.E)) {
// modObj.GetComponent(BoxCollider).enabled = false;
modObj.GetComponent(Rigidbody).isKinematic = true;
modObj.GetComponent(Rigidbody).useGravity = false;
//
initPos = modObj.transform.position;
var initRotation = modObj.transform.rotation;
}
moveObject(modObj, initPos, initRotation);
} else {
// modObj.GetComponent(BoxCollider).enabled = true;
modObj.GetComponent(Rigidbody).isKinematic = false;
modObj.GetComponent(Rigidbody).useGravity = true;
}
}
}
function moveObject(modObj: GameObject, initPos: Vector3, initRotation: Quaternion) {
//Debug.Log("Moving Object");
var hit: RaycastHit;
var foundHit: boolean = false;
foundHit = Physics.Raycast(transform.position, transform.forward, hit);
//Debug.DrawRay(transform.position, transform.forward, Color.blue);
if (foundHit && hit.transform.tag != "Player") {
//Debug.Log("Move to Hit Point: " + hit.point);
modifyObjGUIscript.activateMoveDisplay(initPos, hit.point);
var meshHalfHeight = modObj.GetComponent. < MeshRenderer > ().bounds.size.y / 2; //helps account for large and small objects
// Debug.Log("CurObj Mesh Min: " + meshHalfHeight);
// modObj.transform.position = hit.point; //***method 01***
// modObj.transform.position = Vector3.Lerp(initPos, hit.point, speed); //***method 02***
// modObj.transform.position = Vector3.SmoothDamp(initPos, hit.point, velocity, smoothTime); //***method 02***
var rb = modObj.GetComponent. < Rigidbody > ();
rb.MovePosition(hit.point); //***method 03***
modObj.transform.position.y = modObj.transform.position.y + meshHalfHeight + hoverHeight;
modObj.transform.rotation = initRotation;
}
}
Turns out the issue was being caused by the raycast hitting the object being moved. Resolved this by only allowing hits from the terrain to be used as points to move to.
if(foundHit && hit.transform.tag == "Terrain")

Level Selection menu, camera boundary unity 2d

My level selection menu scene will be a graphic map. Think level selection similar to candy crush. I have different sprites for different maps that will be instantiated when the user moves the camera to that map. In order for me to achieve this, I scroll/move the camera using touch on it's Y-axis. But the problem is, I'm having a trouble getting the boundary of the map sprite, I already read a lot of solution about this one. Here is my current script. I don't know what I'm doing wrong. My camera got stuck when it is near the boundary. Thank you for your help
public float scrollSpeed = 10.0f;
public GameObject[] maps;
Camera mainCamera;
private float topBound;
private float bottomBound;
private Vector3 pos;
private SpriteRenderer currentSprite;
private int mapIndex;
void Awake ()
{
mapIndex = 0;
mainCamera = Camera.main;
currentSprite = maps [mapIndex].GetComponent<SpriteRenderer> ();
bottomBound = currentSprite.sprite.bounds.size.y * -1;
topBound = currentSprite.sprite.bounds.size.y + currentSprite.gameObject.transform.position.y;
}
void Update ()
{
if (Input.touchCount > 0 && Input.GetTouch (0).phase == TouchPhase.Moved)
{
Vector2 touchDeltaPosition = Input.GetTouch(0).deltaPosition;
mainCamera.transform.Translate(0f,-touchDeltaPosition.y * scrollSpeed * Time.deltaTime,0f);
}
}
private float getAxisDelta(float axisDelta,float camMin,float camMax,float bottom,float top)
{
//get where edge of camera will have moved if full translate is done
float boundaryMinPixelsDestination = camMin - Mathf.Abs(axisDelta);
float boundaryMaxPixelsDestination = camMax + Mathf.Abs(axisDelta);
Debug.Log("MaxPixels:"+boundaryMaxPixelsDestination+"="+camMax+"+"+Mathf.Abs(axisDelta));
//check to see if you're within the border
if ((boundaryMinPixelsDestination <= bottom && axisDelta > 0) ||
(boundaryMaxPixelsDestination >= top && axisDelta < 0))
{
axisDelta = 0;
}
return axisDelta;
}
private float camBoundPos(string pos)
{
float bounds = 0f;
if (pos == "top")
bounds = mainCamera.transform.position.y + mainCamera.orthographicSize;
if(pos == "bottom")
bounds = mainCamera.transform.position.y - mainCamera.orthographicSize;
return bounds;
}

Character is not colliding with other other objects in Unity3D

I'm working on a game right now (first 3D styled game), and I have a problem with my character colliding. I have a Player object, which has another object(s) as the real moveable characters (now I have only one). I have rigidbody and box collider too attached to my character. I have made a level (with hand-placed platforms), and I would like avoid my character of falling of the platforms, while the user control it. I have tried to place a cube on the side of the platform(s), with box collider attached to it, but the character not detect the colliding for some reasons. I would like my character to be stopped by the collider "cube", but it doesn't happen.
I use this script to move my object (attached to my character Player object) :
public class Bounce : MonoBehaviour {
float lerpTime;
float currentLerpTime;
float perc = 1;
Vector3 startPos;
Vector3 endPos;
bool firstInput;
public bool justJump;
public GameObject player;
// Update is called once per frame
void Update () {
if (Input.GetButtonDown("up") || Input.GetButtonDown("down") || Input.GetButtonDown("left") || Input.GetButtonDown("right")) {
if (perc == 1) {
lerpTime = 1;
currentLerpTime = 0;
firstInput = true;
justJump = true;
}
}
startPos = gameObject.transform.position;
if (Input.GetButtonDown("up") && gameObject.transform.position == endPos) {
endPos = transform.position + player.transform.rotation * (new Vector3(0, 0, 1f));
}
if (Input.GetButtonDown("down") && gameObject.transform.position == endPos) {
endPos = transform.position + player.transform.rotation * (new Vector3(0, 0, -1f));
}
if (firstInput == true) {
currentLerpTime += Time.deltaTime * 5;
perc = currentLerpTime / lerpTime;
gameObject.transform.position = Vector3.Lerp(startPos, endPos, perc);
if (perc > 0.8f) {
perc = 1;
}
if (Mathf.Round(perc) == 1) {
justJump = false;
}
}
}
void OnCollisionEnter(Collision collision) {
Debug.Log("!!!!!!!");
}
}
And I use this script on the character itself: (to rotate and animate it)
Code (csharp):
public class AnimationController : MonoBehaviour {
Animator anim;
public GameObject thePlayer;
// Use this for initialization
void Start () {
anim = gameObject.GetComponent<Animator>();
}
// Update is called once per frame
void Update () {
Bounce bounceScript = thePlayer.GetComponent<Bounce>();
if (bounceScript.justJump == true) {
anim.SetBool("Jump", true);
}
else {
anim.SetBool("Jump", false);
}
if (Input.GetButtonDown("right")) {
//transform.rotation *= Quaternion.Euler(0,30,0);
transform.RotateAround(transform.position, Vector3.up, 90);
}
if (Input.GetButtonDown("left")) {
transform.Rotate (0, -90, 0, 0);
}
}
}
It's only colliding when the cube not isKinematic, but it doesn't stop my player from getting through the cube for some reason.
I have read some sites about problems like this, but nothing helped yet.
It would be great if you can give me any code improvements :)
EDIT1:
Sorry, for answering so late, I couldn't do anything with my game in the last few days. Today I have tried to do something with raycasts, you can see my code, for my first try just in the update method:
void Update () {
if (Input.GetButtonDown("up") || Input.GetButtonDown("down") || Input.GetButtonDown("left") || Input.GetButtonDown("right")) {
if (perc == 1) {
lerpTime = 1;
currentLerpTime = 0;
firstInput = true;
justJump = true;
}
}
startPos = gameObject.transform.position;
/* if (Input.GetButtonDown("right") && gameObject.transform.position == endPos) {
//endPos = new Vector3(transform.position.x + 0.5f, transform.position.y, transform.position.z);
}
if (Input.GetButtonDown("left") && gameObject.transform.position == endPos) {
endPos = new Vector3(transform.position.x - 0.5f, transform.position.y, transform.position.z);
}*/
Vector3 fwd = player.transform.TransformDirection(Vector3.forward);
RaycastHit objectHit;
if (Physics.Raycast(player.transform.position, fwd, out objectHit, 2)) {
if (objectHit.collider.tag == "Wall") {
Debug.Log("WALL RAYCAST HIT!");
}
}
if (Input.GetButtonDown("up") && gameObject.transform.position == endPos) {
endPos = transform.position + player.transform.rotation * (new Vector3(0, 0, 1f));
}
if (Input.GetButtonDown("down") && gameObject.transform.position == endPos) {
//endPos = transform.position + player.transform.rotation * (new Vector3(0, 0, -1f));
}
if (firstInput == true) {
currentLerpTime += Time.deltaTime * 5;
perc = currentLerpTime / lerpTime;
gameObject.transform.position = Vector3.Lerp(startPos, endPos, perc);
if (perc > 0.8f) {
perc = 1;
}
if (Mathf.Round(perc) == 1) {
justJump = false;
}
}
}
With this I can get the Debug Log WALL RAYCAST HIT 2-3 times at a time, but only once. As I move the character it won't appear again, for some reason (I think it should because the update method is called in every frame).
Although when I place it in the Input.GetButtonDown("up") method, it won't log anything:
if (Input.GetButtonDown("up") && gameObject.transform.position == endPos) {
fwd = player.transform.TransformDirection(Vector3.forward);
if (Physics.Raycast(player.transform.position, fwd, out objectHit, 2)) {
if (objectHit.collider.tag == "Wall") {
Debug.Log("WALL RAYCAST HIT!");
}
}
endPos = transform.position + player.transform.rotation * (new Vector3(0, 0, 1f));
}
When you update the transform.position you actually "teleport" yout object to the new position. Even when you do this smoothly, using something like the Lerp function, as you do on your move script, Unity understands that you are teleporting your object to a new coordinate.
This is not wrong, All games work like that. Functions like Lerp just create the ilusion of movement, so the player fell like the character actually moved from one point to another.
What is happening is that your script keeps telling the character to move to a new position, despite any objects on its path. The collision happens, but your Update function still places the character on ints new position.
I can think of two possible ways for you to solve this:
Create an OnCollisionEnter() function for your Move script that somehow stops your movement. By creating a flag like you did with the firstInput you could achieve this.
Instead of updating your transform.position you could use a rigidbody to handle the movement and collisions for your. This way, everytime you need to move your character you will need to add some velocity to the character rigidbody, instead of directly updating the transform.position.
Since your character doesn't move in a constant way, but in a "one step at a time" way, I think the first solution is a better suitted for you.
The code will be something like this
void OnCollisionenter(Collision collision)
{
collided = true;
}
and the end of your Move script should be updated to
if(!collided)
{
if (firstInput == true) {
currentLerpTime += Time.deltaTime * 5;
perc = currentLerpTime / lerpTime;
transform.position = Vector3.Lerp(startPos, endPos, perc);
if (perc > 0.8f) {
perc = 1;
}
if (Mathf.Round(perc) == 1) {
justJump = false;
}
}
}
else
{
// Remember to reset this when you stop your character
endPos = transform.position;
collided = false;
}
This time I couldn't test the code before writting it here, so you may need to do some changes before it works.
ps: I don't think you need your firstInput variable. Once it is set to true, you never set it to false again. Also, the Input.GetButtonDown() function will only return true on the first frame a button is pressed wich is what I guess you intended when you created firstInput.
ps2: My solution added a collided boolean attribute to your class, so don't forget to add a line private bool collided; with your other class attributes. Also, read that chapter about the state machine pattern I recommended you on your other question. Creating this kind of control attribute suach as the collided boolean is not a good practice and if you had implemented a state machine this could be avoided.
Hey I had a similar problem i was using an animated model from Mixamo.com and I notices that for some strange reason the character didn't collide with boundaries despite having collider, for some reason it didn't work until i added a CharacterController to my model instead of a collider just search for the CharacterController and add it as you would add any script or rigid body to your game object.
Hope it Works XD Greetings