آموزش راه رفتن روی سطح شیب دار در یونیتی walk over slope/tilt surface in unity3d
برای تشخیص شیب از Raycasting() استفاده می شه.
اگه میخوای شیب زمین رو تشخیص بدی پیشنهاد میشه از Colider.Raycast() به جای Physics.Raycast() استفاده کنی.
کد نمونه(js) :
نمی دونم تا چه حد کمکت می کنه ولی یه متنی رو برات ترجمه کردم امیدوارم از هیچی بهتر باشه.
برای تشخیص شیب از Raycasting() استفاده می شه.
اگه میخوای شیب زمین رو تشخیص بدی پیشنهاد میشه از Colider.Raycast() به جای Physics.Raycast() استفاده کنی.
کد نمونه(js) :
var hit : RaycastHit;
var ray = new Ray(transform.position, Vector3.down);
if (someCollider.Raycast(ray, hit)) {
var slope = hit.normal;
//Adjust character based on normal
}
اسکریپت های زیادی برای تنظیم جهت چرخش ابجکت در راستای یک سطح نرمال وجود داره.
مثال:
var someCollider : Collider;
var hit : RaycastHit;
var ray = new Ray(transform.position, Vector3.down);
if (someCollider.Raycast(ray, hit, 1000)) {
transform.rotation = Quaternion.FromToRotation(transform.up, hit.normal) * transform.rotation;
}
همچنین در inspector، زمین(terrain) شیب دار خودتو با ماوس Drag کن(بگیر) و بنداز روی متغیر someCollider در کادر خصوصیات inspector.
به player هم می تونی چند تا کالیدر بدی مثل برخورد کننده ی کپسولی(capsule collider).
برای جلوگیری از فرو رفتن ابجکت هم می تونی چرخش در جهت بردار انتخابی رو freeze کنی و یا اینکه می تونی مقدار پارامتر Drag در کامپوننت rigidbody رو که به ابجکتت دادی زیاد کنی.
منبع :
http://answers.unity3d.com/questions/509...ction.html
------------------------
حرکت یک گیم آبجکت روی سطح شیب دار :
منبع: http://www.asteroidbase.com/devlog/7-lea...w-to-walk/
مترجم : sajjad3011
یک روش آن است که از raycast برای چک کردن collider زیر player (یا شی در حال حرکت روی سطح شیب دار که در اصطلاح به آن Walker هم می گوییم) استفاده کنیم.اما Walker در حین حرکت به اطراف و با توجه به تغییرات باید مثل سنجاب نگاه کند.(منظورش زاویه چرخش هست).در عوض ما دو اشعه(ray) را پرتاب می کنیم.هر کدام برای یک طرف Walker:
bool doubleRaycastDown(TerrainMovementRayProperties movementRay, float rayLength, out RaycastHit leftHitInfo, out RaycastHit rightHitInfo) { Vector3 transformUp = transform.up; Vector3 transformRight = transform.right; Ray leftRay = new Ray(transform.position + movementRay.originOffsetY * transformUp + movementRay.distanceFromCenter * transformRight, -transformUp); Ray rightRay = new Ray(transform.position + movementRay.originOffsetY * transformUp – movementRay.distanceFromCenter * transformRight, -transformUp); return Physics.Raycast(leftRay, out leftHitInfo, rayLength, DefaultTerrainLayerMask) && Physics.Raycast(rightRay, out rightHitInfo, rayLength, DefaultTerrainLayerMask); }
اگر هر دو ray به یک کالیدر با لایه ی مناسب برخورد کرد،ما میانگین position و بردارهای normal نتیجه شده ی ابجکت های RaycastHit را بکار برده و از آنها به ترتیب برای تنظیم و موقعیت دهی Walker استفاده خواهیم کرد.این کار آسان است:
void positionOnTerrain(RaycastHit leftHitInfo, RaycastHit rightHitInfo, float maxRotationDegrees, float positionOffsetY) { Vector3 averageNormal = (leftHitInfo.normal + rightHitInfo.normal) / 2; Vector3 averagePoint = (leftHitInfo.point + rightHitInfo.point) / 2; Quaternion targetRotation = Quaternion.FromToRotation(Vector3.up, averageNormal); Quaternion finalRotation = Quaternion.RotateTowards(transform.rotation, targetRotation, maxRotationDegrees); transform.rotation = Quaternion.Euler(0, 0, finalRotation.eulerAngles.z); transform.position = averagePoint + transform.up * positionOffsetY; }
به Walker اجازه دهید تا بچرخد .شاید در هنگام مواجهه با چاله ها و شکاف
ها،در هر فریم کمی حرکت تند و عصبی داشته باشد.برای رفع این مشکل کافیست
میزان چرخش را با استفاده از Quaternion.RotateTowards محدود نماییم.
در این روش،برای اینکه یک حرکت واقع گرایانه تری داشته باشیم باید کمی
بیشتر راه رویم.همچنین Walker تمایل به گیر کردن در انواع خاصی از چاله ها و
گودی ها دارد.برای غلبه بر این مشکل ما یک اشعه ی افقی کوتاه را در جهت
حرکت،اضافه کردیم که تا حد لبه ی بدن کاراکتر بسط می یابد.اگر این ray با
هر قطعه از زمین برخورد(collide) کند،اشعه ی رو به پایین(downward ray)آن
سمت از Walker را باطل می کند.
if(rigidbody.velocity.sqrMagnitude > 0) { //if moving left if(MathUtilities.VectorSimilarity(rigidbody.velocity, selfTransform.right) > 0) { RaycastHit overrideLeftHitInfo; Ray overrideLeftRay = new Ray(transform.position + horizontalRayProperties.originOffsetY * selfTransform.up, selfTransform.right); if(Physics.Raycast(overrideLeftRay, out overrideLeftHitInfo, horizontalRayProperties.attachedRayLength, DefaultTerrainLayerMask)) { leftHitInfo = overrideLeftHitInfo; } } //if moving right else { RaycastHit overrideRightHitInfo; Ray overrideRightRay = new Ray(transform.position + horizontalRayProperties.originOffsetY * selfTransform.up, -selfTransform.right); if(Physics.Raycast(overrideRightRay, out overrideRightHitInfo, horizontalRayProperties.attachedRayLength, DefaultTerrainLayerMask)) { rightHitInfo = overrideRightHitInfo; } } }
در شکل زیر نحوه ی علکرد این سیستم را می بینید.
خطوط زرد و قرمز اشعه های پرتابی از طرف Walker را نشان می دهند.
خطوط بنفش و سبز،نرمال های تولید شده از ray های برخوردی با زمین را نشان می دهند.
خط آبی فیروزه ای ،میانگین آن نرمال ها،از نقطه ی وسط Walker در برخورد با زمین است.
اشعه ی باطل کردن افقی(horizontal override ray) در شکل نشان داده نشده.
دشمن کهکشانی در حال حرکت رو ترکیبی از collider ها مثل sphere collider و
capsule collider می باشد اما این سیستم مثل همان mesh collider به خوبی
کار می کند.
فقط همین داداش