Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 11 Next capture
2021 2022 2023
1 capture
11 Jun 22 - 11 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
This question was closed Oct 12, 2017 at 04:11 AM by jabez for the following reason:

Made a new system

avatar image
1
Question by jabez · Jul 10, 2015 at 05:11 PM · c#meshedge

Find edge/surface/ledge of mesh

Hello, I've been messing around with my character & i need to find out a way to detect if there's an edge/surface/ledge so the character can grab on to it.

Take the image below for example

alt text

I would like to detect the areas that are lined red & that are an edge/surface using C# so the character can grab on to it.

Any help would be appreciated, thanks! - Jabez

cube.jpg (111.9 kB)
Comment
Add comment · Show 9
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image pgomes · Jul 10, 2015 at 05:19 PM 0
Share

Is this for a render effect or do you need them for script logic?

Is this intended for character climbing?

avatar image adriandevera · Jul 10, 2015 at 05:43 PM 0
Share

Seems like it may be for base building?

ie need only certain objects to snap at certain locations

avatar image jabez · Jul 10, 2015 at 06:18 PM 0
Share

Thanks for the replies. Tis for character climbing, I need it to be dynamic.

avatar image _Gkxd · Jul 10, 2015 at 08:08 PM 2
Share

If you can access the triangles, you can say that there's an edge between two triangles if the triangles are adjacent and the normal vectors of those triangles differ by a certain angle. The normal vector of a triangle can be obtained by taking the cross product of two of its sides as vectors, then normalizing.

If you need to detect if a triangle faces up, you can compare the normal of the triangle with Vector3.up and get the angle between them.

I think using invisible colliders would be easier though.

avatar image Lahzar · Jul 10, 2015 at 09:34 PM 1
Share

@_Gkxd Didn't think of that when I tried! I remember all I did was I got the vertecies of the mesh the player hit, and then checked for vertecies with equal values on exactly two vectors, but that didn't work and I got bored so... This question has resparked my interest in this, I know what I will be doing tomorrow! Hope somebody has a complete answer, though! GL guys

Show more comments

3 Replies

  • Sort: 
avatar image
3
Best Answer

Answer by Lahzar · Jul 11, 2015 at 07:33 PM

So I have been trying to do something with this all day long. And I managed to get the quad that the player hits, get the top edge of it and check if it is climable. I think it only works with perfect quads, and its not very good at all, but it works. So its far from perfect but its a good base for you to start building on!

 using UnityEngine;
 using System.Collections;
 //using System.Collections.Generic;
 //using System.Threading;
 
 //TODO Clean up stuff. Fix bug and tweak stuff. Optimize stuff. Animation support. Add climbing support. Make usable for non-perfect quads. Find all edges within reach instead of just the closest.
 //Made in a day by Imre Angelo aka Lahzar @ the unity forums - Enjoy!
 public class RunFree3o : MonoBehaviour {
         public float reach = 3;    //TODO Check from players arms, legs etc
 private Vector3[] quad;
 private Vector3[] top;

 void Start()    {
     quad = new Vector3[4];
 }

 void Update()    {
     if(top[0] != new Vector3())
         Debug.DrawLine(top[0], top[1], Color.green, 1);
 }

 void OnControllerColliderHit(ControllerColliderHit col)    {
     RaycastHit hit;
     Debug.DrawRay(col.point, col.moveDirection, Color.blue, 1);
     if(Physics.Raycast(transform.position, col.moveDirection, out hit, 0.5f))    {
         if(hit.normal.y == transform.position.y-(GetComponent<CharacterController>().height/2))
             return;

         MeshCollider meshCollider = hit.collider as MeshCollider;
         if (meshCollider == null || meshCollider.sharedMesh == null)
             return;
         
         Mesh mesh = meshCollider.sharedMesh;
         Vector3[] vertices = mesh.vertices;
         int[] triangles = mesh.triangles;
         Transform hitTransform = hit.collider.transform;

         StartCoroutine(CoroutineThing(mesh, hitTransform, vertices, triangles, hit.triangleIndex));
     }
 }

 IEnumerator CoroutineThing(Mesh mesh, Transform hitTransform, Vector3[] vertices, int[] triangles, int triangleIndex)    {
     #region Get hit triangle
     Vector3 p0 = vertices[triangles[triangleIndex * 3 + 0]];
     Vector3 p1 = vertices[triangles[triangleIndex * 3 + 1]];
     Vector3 p2 = vertices[triangles[triangleIndex * 3 + 2]];
     p0 = hitTransform.TransformPoint(p0);
     p1 = hitTransform.TransformPoint(p1);
     p2 = hitTransform.TransformPoint(p2);
     #endregion

     Debug.DrawLine(p0, p1, Color.blue, 4);
     Debug.DrawLine(p1, p2, Color.blue, 4);
     Debug.DrawLine(p2, p0, Color.blue, 4);

     #region Get last triangle
     Vector3 p3 = new Vector3();
     for(int i = 10; i > -10; i--)    {
         Vector3 p4 = new Vector3();
         if(vertices[triangles[triangleIndex * 3 + i]] == null)
             continue;

         try {
             p4 = hitTransform.TransformPoint(vertices[triangles[triangleIndex * 3 + i]]);
         } catch (System.Exception ex)    {
             ex.Source = "ignore";
             continue;
         }

         if(p4 != p0 && p4 != p1 && p4 != p2)    {

             int ex = 0, wai = 0, zed = 0;
             if(Mathf.FloorToInt(p4.x) == Mathf.FloorToInt(p0.x))    {    ex++;    }
             if(Mathf.FloorToInt(p4.y) == Mathf.FloorToInt(p0.y))    {    wai++;    }
             if(Mathf.FloorToInt(p4.z) == Mathf.FloorToInt(p0.z))    {    zed++;    }
             if(Mathf.FloorToInt(p4.x) == Mathf.FloorToInt(p1.x))    {    ex++;    }
             if(Mathf.FloorToInt(p4.y) == Mathf.FloorToInt(p1.y))    {    wai++;    }
             if(Mathf.FloorToInt(p4.z) == Mathf.FloorToInt(p1.z))    {    zed++;    }
             if(Mathf.FloorToInt(p4.x) == Mathf.FloorToInt(p2.x))    {    ex++;    }
             if(Mathf.FloorToInt(p4.y) == Mathf.FloorToInt(p2.y))    {    wai++;    }
             if(Mathf.FloorToInt(p4.z) == Mathf.FloorToInt(p2.z))    {    zed++;    }
             
             if(ex+wai+zed == 5)    {
                 if(wai == 1)    {
                     p3 = p4;
                     break;
                 }
             }
         }
     }
     #endregion
     
     Debug.DrawLine(p0, p3, Color.red, 4);
     Debug.DrawLine(p1, p3, Color.red, 4);
     Debug.DrawLine(p2, p3, Color.red, 4);

     if(p3 != new Vector3())    {
         quad = new Vector3[4];
         quad[3] = p3;
     }

     quad[0] = p0;
     quad[1] = p1;
     quad[2] = p2;

     StartCoroutine(CheckMoves());
     yield return null;
 }



 IEnumerator CheckMoves()    {
     top = new Vector3[2];
     foreach(Vector3 v in quad)    {
         if(v == new Vector3())
             continue;

         if(Mathf.FloorToInt(v.y) == Mathf.FloorToInt(top[0].y) && v.y > top[1].y)    {
             top[1] = top[0];
             top[0] = v;
         } else if(v.y > top[0].y)    {
             top[1] = top[0];
             top[0] = v;
         }
     }

     if(Vector3.Distance(transform.position, (top[0]+top[1])/2) <= reach)    {  //This code block doesn't always work!
         if(!Physics.CheckCapsule((top[0]+top[1])/2, (top[0]+top[1])/2+Vector3.up*2, 0.5f) && !Physics.Raycast((top[0]+top[1])/2+Vector3.up*2, Vector3.down, 1.95f))    {
             if(Physics.Raycast((top[0]+top[1])/2+Vector3.up*2+transform.forward/2, Vector3.down, 2.1f))    {
                 transform.position = (top[0]+top[1])/2+Vector3.up*2;
             }
         }
     }

     yield return null;
 }
 }


First it gets the triangle that the players controllercollider hits. Then it Tries to figure out which vertex is the needed vertex to find the adjacent triangle and thus the whole quad. Now that its sure there is a level top edge, it finds the highest edge. Then it checks if the standard unity FPS controller can fit ontop of said edge! That last part is buggy but it works okay. Try it for yourself!

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Lahzar · Jul 11, 2015 at 07:35 PM 0
Share

The big thing to do next is get all edges within reach, and not just the ones that are part of the quad hit by ControllerColliderHit. Also your mesh HAS to be read/write enabled I think!

avatar image jabez · Jul 13, 2015 at 07:15 AM 0
Share

This script actually works wonders C:, Thanks for sharing. I will edit it to suit my needs & send you copies of it :D. Thanks for your help.

avatar image
3

Answer by pgomes · Jul 10, 2015 at 08:08 PM

Since the mesh is going to be dynamic, I suggest detecting the edge on the fly with casts. See the following picture:

alt text

You do a sphere cast (or horizontal raycast alternatively) above the character to detect if there is no vertical surface to climb to. You do a vertical raycast above and forward to detect if it is an actual edge. I used this technique successfully for a similar problem.

This approach does assume that you are generating/updating a collider mesh that matches the rendered mesh, or a proxy for that mesh (e.g. set of box colliders). If you have control over the colliders you might also want to separate the vertical and horizontal ones and tagged them differently for more specific checks.


climb-modified.jpg (219.8 kB)
Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image jabez · Jul 11, 2015 at 03:11 AM 0
Share

Thanks for this information i actually saw a video that used a similar technique, I'll try it out a bit later when i get time & let you know how it goes :D.

avatar image starikcetin · Jul 11, 2015 at 07:37 PM 0
Share

thumbs up for drawing!

avatar image
0

Answer by PixelSpartan · Jul 10, 2015 at 06:19 PM

Put invisible trigger colliders

Comment
Add comment · Show 7 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image jabez · Jul 10, 2015 at 07:37 PM 0
Share

Thanks for the suggestion but my meshes are procedural so would not be possible. This would work otherwise.

avatar image tanoshimi · Jul 10, 2015 at 07:42 PM 0
Share

So just procedurally-generate the colliders as you procedurally-generate the mesh...

avatar image jabez · Jul 10, 2015 at 07:59 PM 0
Share

The only thing is to generate the colliders i need to know where the edge/ledge/surface is & that's why i'm asking this question. Also, i'm not asking how to add colliders or anything to do with colliders, i'm asking how to find the edge/surface/ledge of a mesh.

avatar image tanoshimi · Jul 10, 2015 at 08:05 PM 0
Share

And I'm suggesting that, if your mesh is generated procedurally, the edges can be deter$$anonymous$$ed entirely as a product of the procedure, no?

avatar image pgomes · Jul 10, 2015 at 08:11 PM 1
Share

What is your starting data structure/description of the mesh?

Show more comments

Follow this Question

Answers Answers and Comments

26 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Multiple Cars not working 1 Answer

Distribute terrain in zones 3 Answers

How to remove white blinking edge on mesh? 1 Answer

Executing code on touching edges of a collider from the inside 0 Answers

Spawned Object Gradient Mesh Colors? 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges