(Unity2D) Switch movement style on collision












0














I have a player character in a topdown game that moves in grid-like movements (1 unit at a time), but when it hits a patch of ice (square), I want it to switch to lerp-movement, slide to the edge, and stop.



Currently I have 5 different colliders as children for each patch of ice: the ice collider itself, and 4 slightly distanced colliders, one for each side of the ice. When it hits the ice collider, depending on which direction it was heading in, it should lerp to the distanced collider associated.



Like so (it's hard to see the main collider but it's there):
ice



Here is the code I have been using for the down key (its basically the same for all keys):



else if (Input.GetKeyDown(KeyCode.DownArrow))
{
Vector2 movementDown = new Vector2(0, -1);
RaycastHit2D hitDown = Physics2D.Raycast(transform.position, movementDown, 0.05f);

if (hitDown.collider && hitDown.collider.gameObject.tag == "barrier")
{
Debug.Log("N/A");
}
else if (onIce)
{
player.transform.position = Vector3.Lerp(transform.position, downIce.transform.position, 100 * Time.fixedDeltaTime);
}
else
{
player.transform.position += new Vector3(movementDown.x, movementDown.y, -0.1f);
}
}


EDIT: code that updates bool 'onIce':



void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "ice") {
onIce = true;
}
}

void OnTriggerExit2D(Collider2D collision)
{
if (collision.gameObject.tag == "ice")
{
onIce = false;
}
}









share|improve this question
























  • So, whats exactly the problem?
    – Hesamom
    Nov 20 at 6:58










  • It's not sliding. It keeps using the 'else' case.
    – Kat K
    Nov 20 at 7:30










  • you should post the code that updates the "onIce" variable.
    – Lotan
    Nov 20 at 8:06










  • @Lotan I have updated it.
    – Kat K
    Nov 20 at 8:10






  • 1




    Is your collider a Trigger? If not, try OnCollisionEnter. Also try a non-friction physics material (assign it on the ice collider)
    – KYL3R
    Nov 20 at 8:18
















0














I have a player character in a topdown game that moves in grid-like movements (1 unit at a time), but when it hits a patch of ice (square), I want it to switch to lerp-movement, slide to the edge, and stop.



Currently I have 5 different colliders as children for each patch of ice: the ice collider itself, and 4 slightly distanced colliders, one for each side of the ice. When it hits the ice collider, depending on which direction it was heading in, it should lerp to the distanced collider associated.



Like so (it's hard to see the main collider but it's there):
ice



Here is the code I have been using for the down key (its basically the same for all keys):



else if (Input.GetKeyDown(KeyCode.DownArrow))
{
Vector2 movementDown = new Vector2(0, -1);
RaycastHit2D hitDown = Physics2D.Raycast(transform.position, movementDown, 0.05f);

if (hitDown.collider && hitDown.collider.gameObject.tag == "barrier")
{
Debug.Log("N/A");
}
else if (onIce)
{
player.transform.position = Vector3.Lerp(transform.position, downIce.transform.position, 100 * Time.fixedDeltaTime);
}
else
{
player.transform.position += new Vector3(movementDown.x, movementDown.y, -0.1f);
}
}


EDIT: code that updates bool 'onIce':



void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "ice") {
onIce = true;
}
}

void OnTriggerExit2D(Collider2D collision)
{
if (collision.gameObject.tag == "ice")
{
onIce = false;
}
}









share|improve this question
























  • So, whats exactly the problem?
    – Hesamom
    Nov 20 at 6:58










  • It's not sliding. It keeps using the 'else' case.
    – Kat K
    Nov 20 at 7:30










  • you should post the code that updates the "onIce" variable.
    – Lotan
    Nov 20 at 8:06










  • @Lotan I have updated it.
    – Kat K
    Nov 20 at 8:10






  • 1




    Is your collider a Trigger? If not, try OnCollisionEnter. Also try a non-friction physics material (assign it on the ice collider)
    – KYL3R
    Nov 20 at 8:18














0












0








0







I have a player character in a topdown game that moves in grid-like movements (1 unit at a time), but when it hits a patch of ice (square), I want it to switch to lerp-movement, slide to the edge, and stop.



Currently I have 5 different colliders as children for each patch of ice: the ice collider itself, and 4 slightly distanced colliders, one for each side of the ice. When it hits the ice collider, depending on which direction it was heading in, it should lerp to the distanced collider associated.



Like so (it's hard to see the main collider but it's there):
ice



Here is the code I have been using for the down key (its basically the same for all keys):



else if (Input.GetKeyDown(KeyCode.DownArrow))
{
Vector2 movementDown = new Vector2(0, -1);
RaycastHit2D hitDown = Physics2D.Raycast(transform.position, movementDown, 0.05f);

if (hitDown.collider && hitDown.collider.gameObject.tag == "barrier")
{
Debug.Log("N/A");
}
else if (onIce)
{
player.transform.position = Vector3.Lerp(transform.position, downIce.transform.position, 100 * Time.fixedDeltaTime);
}
else
{
player.transform.position += new Vector3(movementDown.x, movementDown.y, -0.1f);
}
}


EDIT: code that updates bool 'onIce':



void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "ice") {
onIce = true;
}
}

void OnTriggerExit2D(Collider2D collision)
{
if (collision.gameObject.tag == "ice")
{
onIce = false;
}
}









share|improve this question















I have a player character in a topdown game that moves in grid-like movements (1 unit at a time), but when it hits a patch of ice (square), I want it to switch to lerp-movement, slide to the edge, and stop.



Currently I have 5 different colliders as children for each patch of ice: the ice collider itself, and 4 slightly distanced colliders, one for each side of the ice. When it hits the ice collider, depending on which direction it was heading in, it should lerp to the distanced collider associated.



Like so (it's hard to see the main collider but it's there):
ice



Here is the code I have been using for the down key (its basically the same for all keys):



else if (Input.GetKeyDown(KeyCode.DownArrow))
{
Vector2 movementDown = new Vector2(0, -1);
RaycastHit2D hitDown = Physics2D.Raycast(transform.position, movementDown, 0.05f);

if (hitDown.collider && hitDown.collider.gameObject.tag == "barrier")
{
Debug.Log("N/A");
}
else if (onIce)
{
player.transform.position = Vector3.Lerp(transform.position, downIce.transform.position, 100 * Time.fixedDeltaTime);
}
else
{
player.transform.position += new Vector3(movementDown.x, movementDown.y, -0.1f);
}
}


EDIT: code that updates bool 'onIce':



void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "ice") {
onIce = true;
}
}

void OnTriggerExit2D(Collider2D collision)
{
if (collision.gameObject.tag == "ice")
{
onIce = false;
}
}






unity3d collision-detection lerp






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 20 at 8:09

























asked Nov 20 at 0:15









Kat K

325




325












  • So, whats exactly the problem?
    – Hesamom
    Nov 20 at 6:58










  • It's not sliding. It keeps using the 'else' case.
    – Kat K
    Nov 20 at 7:30










  • you should post the code that updates the "onIce" variable.
    – Lotan
    Nov 20 at 8:06










  • @Lotan I have updated it.
    – Kat K
    Nov 20 at 8:10






  • 1




    Is your collider a Trigger? If not, try OnCollisionEnter. Also try a non-friction physics material (assign it on the ice collider)
    – KYL3R
    Nov 20 at 8:18


















  • So, whats exactly the problem?
    – Hesamom
    Nov 20 at 6:58










  • It's not sliding. It keeps using the 'else' case.
    – Kat K
    Nov 20 at 7:30










  • you should post the code that updates the "onIce" variable.
    – Lotan
    Nov 20 at 8:06










  • @Lotan I have updated it.
    – Kat K
    Nov 20 at 8:10






  • 1




    Is your collider a Trigger? If not, try OnCollisionEnter. Also try a non-friction physics material (assign it on the ice collider)
    – KYL3R
    Nov 20 at 8:18
















So, whats exactly the problem?
– Hesamom
Nov 20 at 6:58




So, whats exactly the problem?
– Hesamom
Nov 20 at 6:58












It's not sliding. It keeps using the 'else' case.
– Kat K
Nov 20 at 7:30




It's not sliding. It keeps using the 'else' case.
– Kat K
Nov 20 at 7:30












you should post the code that updates the "onIce" variable.
– Lotan
Nov 20 at 8:06




you should post the code that updates the "onIce" variable.
– Lotan
Nov 20 at 8:06












@Lotan I have updated it.
– Kat K
Nov 20 at 8:10




@Lotan I have updated it.
– Kat K
Nov 20 at 8:10




1




1




Is your collider a Trigger? If not, try OnCollisionEnter. Also try a non-friction physics material (assign it on the ice collider)
– KYL3R
Nov 20 at 8:18




Is your collider a Trigger? If not, try OnCollisionEnter. Also try a non-friction physics material (assign it on the ice collider)
– KYL3R
Nov 20 at 8:18












1 Answer
1






active

oldest

votes


















0














Lerp is only getting called once, when you push the button. One way to fix it is by using a coroutine:



IEnumerator Slide() {
var t = 0f;
var start = player.transform.position; //we will change the position every frame
//so for lerp to work, we need to save it here.
var end = downIce.transform.position;
while(t < 1f){
t += Time.deltaTime;
player.transform.position = Vector3.Lerp(start, end , t);
yield return null; //returning null waits until the next frame
}
}


And then you use it like this:



...
else if (onIce)
{
this.StartCoroutine(this.Slide());
}
else
...


I think this is still not exactly what you want in your game because it will lerp to the center of the collider. If that's the case you can easily fix it by changing how it calculates the end variable in the coroutine to make the player only slide along the correct axis.






share|improve this answer





















  • It could also be off by one move.. because onIce will not be true until after you have already stepped on the ice. At the time of pressing the button when you first walk onto the ice, the player is not on the ice yet, and the trigger hasn't been hit yet.
    – Leo Bartkus
    Nov 21 at 5:28












  • I fixed the 'lerping to center issue' by changing 'end' to a Vector2, and making its x or y coordinate of 'end' the same as the player's, depending on which trigger it collided with. (i.e. if it hits the left trigger, use the player's y coordinate, etc.)
    – Kat K
    Nov 29 at 4:31











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53384462%2funity2d-switch-movement-style-on-collision%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














Lerp is only getting called once, when you push the button. One way to fix it is by using a coroutine:



IEnumerator Slide() {
var t = 0f;
var start = player.transform.position; //we will change the position every frame
//so for lerp to work, we need to save it here.
var end = downIce.transform.position;
while(t < 1f){
t += Time.deltaTime;
player.transform.position = Vector3.Lerp(start, end , t);
yield return null; //returning null waits until the next frame
}
}


And then you use it like this:



...
else if (onIce)
{
this.StartCoroutine(this.Slide());
}
else
...


I think this is still not exactly what you want in your game because it will lerp to the center of the collider. If that's the case you can easily fix it by changing how it calculates the end variable in the coroutine to make the player only slide along the correct axis.






share|improve this answer





















  • It could also be off by one move.. because onIce will not be true until after you have already stepped on the ice. At the time of pressing the button when you first walk onto the ice, the player is not on the ice yet, and the trigger hasn't been hit yet.
    – Leo Bartkus
    Nov 21 at 5:28












  • I fixed the 'lerping to center issue' by changing 'end' to a Vector2, and making its x or y coordinate of 'end' the same as the player's, depending on which trigger it collided with. (i.e. if it hits the left trigger, use the player's y coordinate, etc.)
    – Kat K
    Nov 29 at 4:31
















0














Lerp is only getting called once, when you push the button. One way to fix it is by using a coroutine:



IEnumerator Slide() {
var t = 0f;
var start = player.transform.position; //we will change the position every frame
//so for lerp to work, we need to save it here.
var end = downIce.transform.position;
while(t < 1f){
t += Time.deltaTime;
player.transform.position = Vector3.Lerp(start, end , t);
yield return null; //returning null waits until the next frame
}
}


And then you use it like this:



...
else if (onIce)
{
this.StartCoroutine(this.Slide());
}
else
...


I think this is still not exactly what you want in your game because it will lerp to the center of the collider. If that's the case you can easily fix it by changing how it calculates the end variable in the coroutine to make the player only slide along the correct axis.






share|improve this answer





















  • It could also be off by one move.. because onIce will not be true until after you have already stepped on the ice. At the time of pressing the button when you first walk onto the ice, the player is not on the ice yet, and the trigger hasn't been hit yet.
    – Leo Bartkus
    Nov 21 at 5:28












  • I fixed the 'lerping to center issue' by changing 'end' to a Vector2, and making its x or y coordinate of 'end' the same as the player's, depending on which trigger it collided with. (i.e. if it hits the left trigger, use the player's y coordinate, etc.)
    – Kat K
    Nov 29 at 4:31














0












0








0






Lerp is only getting called once, when you push the button. One way to fix it is by using a coroutine:



IEnumerator Slide() {
var t = 0f;
var start = player.transform.position; //we will change the position every frame
//so for lerp to work, we need to save it here.
var end = downIce.transform.position;
while(t < 1f){
t += Time.deltaTime;
player.transform.position = Vector3.Lerp(start, end , t);
yield return null; //returning null waits until the next frame
}
}


And then you use it like this:



...
else if (onIce)
{
this.StartCoroutine(this.Slide());
}
else
...


I think this is still not exactly what you want in your game because it will lerp to the center of the collider. If that's the case you can easily fix it by changing how it calculates the end variable in the coroutine to make the player only slide along the correct axis.






share|improve this answer












Lerp is only getting called once, when you push the button. One way to fix it is by using a coroutine:



IEnumerator Slide() {
var t = 0f;
var start = player.transform.position; //we will change the position every frame
//so for lerp to work, we need to save it here.
var end = downIce.transform.position;
while(t < 1f){
t += Time.deltaTime;
player.transform.position = Vector3.Lerp(start, end , t);
yield return null; //returning null waits until the next frame
}
}


And then you use it like this:



...
else if (onIce)
{
this.StartCoroutine(this.Slide());
}
else
...


I think this is still not exactly what you want in your game because it will lerp to the center of the collider. If that's the case you can easily fix it by changing how it calculates the end variable in the coroutine to make the player only slide along the correct axis.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 21 at 5:21









Leo Bartkus

831411




831411












  • It could also be off by one move.. because onIce will not be true until after you have already stepped on the ice. At the time of pressing the button when you first walk onto the ice, the player is not on the ice yet, and the trigger hasn't been hit yet.
    – Leo Bartkus
    Nov 21 at 5:28












  • I fixed the 'lerping to center issue' by changing 'end' to a Vector2, and making its x or y coordinate of 'end' the same as the player's, depending on which trigger it collided with. (i.e. if it hits the left trigger, use the player's y coordinate, etc.)
    – Kat K
    Nov 29 at 4:31


















  • It could also be off by one move.. because onIce will not be true until after you have already stepped on the ice. At the time of pressing the button when you first walk onto the ice, the player is not on the ice yet, and the trigger hasn't been hit yet.
    – Leo Bartkus
    Nov 21 at 5:28












  • I fixed the 'lerping to center issue' by changing 'end' to a Vector2, and making its x or y coordinate of 'end' the same as the player's, depending on which trigger it collided with. (i.e. if it hits the left trigger, use the player's y coordinate, etc.)
    – Kat K
    Nov 29 at 4:31
















It could also be off by one move.. because onIce will not be true until after you have already stepped on the ice. At the time of pressing the button when you first walk onto the ice, the player is not on the ice yet, and the trigger hasn't been hit yet.
– Leo Bartkus
Nov 21 at 5:28






It could also be off by one move.. because onIce will not be true until after you have already stepped on the ice. At the time of pressing the button when you first walk onto the ice, the player is not on the ice yet, and the trigger hasn't been hit yet.
– Leo Bartkus
Nov 21 at 5:28














I fixed the 'lerping to center issue' by changing 'end' to a Vector2, and making its x or y coordinate of 'end' the same as the player's, depending on which trigger it collided with. (i.e. if it hits the left trigger, use the player's y coordinate, etc.)
– Kat K
Nov 29 at 4:31




I fixed the 'lerping to center issue' by changing 'end' to a Vector2, and making its x or y coordinate of 'end' the same as the player's, depending on which trigger it collided with. (i.e. if it hits the left trigger, use the player's y coordinate, etc.)
– Kat K
Nov 29 at 4:31


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53384462%2funity2d-switch-movement-style-on-collision%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

"Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

Alcedinidae

RAC Tourist Trophy