2013-03-26 47 views
5

Tôi đang viết nền tảng 2D trong Unity và tôi đang cố gắng để người chơi tiếp tục sử dụng nền tảng di chuyển. Tôi đã tìm kiếm và nhắn tin cho một hoặc hai ngày, và tôi không có may mắn.Ở trên các nền tảng di chuyển

Về cơ bản, tôi đã được yêu cầu cố giữ cho nhân vật di chuyển với nền tảng khi họ chạm vào. Thứ nhất, nếu tôi sử dụng bất cứ điều gì liên quan đến OnTriggerEnter(), người chơi sẽ đi qua nền tảng này. Nếu tôi làm OnCollisionEnter() (với một CharacterController trên máy nghe nhạc và một BoxCollider trên nền tảng), không có gì xảy ra cả. Đây là hai điều tôi đã tìm thấy nhiều nhất. Người kia là nuôi dạy con người chơi với nền tảng, nhưng điều này dường như gây ra "vấn đề" (thường xuyên nói, không bao giờ giải thích).

Vì vậy, làm cách nào để người chơi có thể ở lại trên nền tảng di chuyển? Đây là mã cho nền tảng di chuyển:

public class MovingPlatform : MonoBehaviour 
{ 
private float useSpeed; 
public float directionSpeed = 9.0f; 
float origY; 
public float distance = 10.0f; 

// Use this for initialization 
void Start() 
{ 
    origY = transform.position.y; 
    useSpeed = -directionSpeed; 
} 

// Update is called once per frame 
void Update() 
{ 
    if(origY - transform.position.y > distance) 
    { 
     useSpeed = directionSpeed; //flip direction 
    } 
    else if(origY - transform.position.y < -distance) 
    { 
     useSpeed = -directionSpeed; //flip direction 
    } 
    transform.Translate(0,useSpeed*Time.deltaTime,0); 
} 

VÀ đây là mã cho phong trào của Player (trong Cập nhật):

CharacterController controller = GetComponent<CharacterController>(); 
    float rotation = Input.GetAxis("Horizontal"); 
    if(controller.isGrounded) 
    { 
     moveDirection.Set(rotation, 0, 0); //moveDirection = new Vector3(rotation, 0, 0); 
     moveDirection = transform.TransformDirection(moveDirection); 

     //running code 
     if(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) //check if shift is held 
     { running = true; } 
     else 
     { running = false; } 

     moveDirection *= running ? runningSpeed : walkingSpeed; //set speed 

     //jump code 
     if(Input.GetButtonDown("Jump")) 
     { 
      //moveDirection.y = jumpHeight; 
      jump(); 
     } 
    } 
    moveDirection.y -= gravity * Time.deltaTime; 
    controller.Move(moveDirection * Time.deltaTime); 

EDIT: Tôi nghĩ rằng nó có thể có để làm với cách tôi m xác định trình phát và nền tảng, nhưng tôi đã thử các kết hợp khác nhau. Nếu nền tảng là một kích hoạt (trên máy va chạm của nó), thì người chơi sẽ xuyên suốt nó. Nếu không, tôi không thể sử dụng chức năng OnTrigger. Tôi có một người cứng nhắc gắn liền với cả người chơi và nền tảng, nhưng nó dường như không ảnh hưởng gì cả. Khi người chơi KHÔNG nhận được trên nền tảng trong một số thiết lập, anh ta jitters và thường chỉ kết thúc lên qua.

+0

Tôi chưa bao giờ sử dụng Unity3D, nhưng là nó có thể làm điều gì đó như 'moveDirection + = thePlatform.moveDirection' khi ký tự nằm trên một nền tảng? – mbeckish

+0

Tôi đã thử điều đó, nhưng dường như tôi gặp sự cố với các chức năng của OnTrigger và OnCollision, điều này sẽ chịu trách nhiệm về phần "khi người chơi ở trên nền tảng". Tôi nghĩ rằng nó đã làm với cách tôi đang xác định các đối tượng của tôi, nhưng tôi không chắc chắn về cách thích hợp để xác định chúng như vậy mà điều này có thể làm việc. – muttley91

+0

Ngoài ra, bạn sẽ cần phải đảm bảo rằng moveDirection.y của ký tự không bao giờ nhỏ hơn moveDirection.y của nền tảng của bạn, nếu không bạn sẽ rơi qua (trừ khi khung Unity3D xử lý cho bạn một cách tự động?) – mbeckish

Trả lời

1

Những gì bạn cần có vẻ là một máy gia tốc thứ hai trên nền tảng này. Máy va chạm chính có isTrigger = false để đảm bảo rằng bộ điều khiển ký tự của bạn đang hoạt động. Chế độ thứ hai chạy với isTrigger = true và chức năng duy nhất của nó là phát hiện rằng trình phát là loại gắn với nền tảng khi OnTriggerEnter được gọi và rời khỏi nền tảng trên OnTriggerExit.

Vì bạn không thể có 2 máy va chạm cùng loại (tôi đoán bạn cần hộp va chạm), hãy xây dựng một đứa trẻ trống bên dưới đối tượng trò chơi nền tảng của bạn và gán máy va chạm hộp cho nó. Tôi thường lấy một vật liệu vật lý đặc biệt gọi là ActionMaterial để làm sạch công cụ của tôi. Nếu bạn đang sử dụng các lớp và có ma trận va chạm được tinh chỉnh, hãy đảm bảo rằng va chạm của bạn được xử lý bởi physX.

+0

Tôi có thể sử dụng hai máy va chạm khác nhau (một hộp, một viên nang) trên cùng một đối tượng cho cùng một hiệu ứng, thay vì có 2 đối tượng và cả hai đều cần kịch bản di chuyển? Ngoài ra, tôi không sử dụng các lớp và không có ma trận va chạm được tinh chỉnh. – muttley91

+0

Máy va chạm khác nhau được cho phép. Nhưng nhớ rằng một máy va chạm viên là đắt hơn nhiều. Vì vậy, nếu có hình dạng khối lập phương, bạn nên sử dụng giải pháp đối tượng con. Không có lớp nào, không có thao tác ma trận va chạm => không tăng độ phức tạp;) Bạn chỉ cần công cụ đó khi bạn đang gặp sự cố về hiệu suất. Tôi đang phát triển cho iOS nên hiệu suất luôn là vấn đề đối với tôi – Kay

+0

Ah đủ công bằng! Vì vậy, để được rõ ràng, bạn có nghĩa là có hai đối tượng trò chơi trong cảnh? Làm thế nào để bạn đặc biệt làm cho một đối tượng một đứa trẻ khác? – muttley91

1

Đây không phải là cách tốt nhất để làm điều đó, nhưng bạn có thể thực hiện một RayCast từ trình phát đến nền tảng di chuyển. Nếu RayCast truy cập "MovingPlatform", bạn có thể kiểm tra sự khác biệt trên trục Y để xác định xem trình phát có đủ gần để nó được coi là "OnThePlatform" hay không. Sau đó, bạn chỉ có thể điều chỉnh vị trí của người chơi như bình thường.

Một ví dụ sẽ là:

private bool isOnMovingPlatform; 
private float offsetToKeepPlayerAbovePlatform = 2.2f; 
private float min = 0.2f; 
private float max = 1.2f; 

private void Update() 
{ 
RaycastHit hit; 
if(Physics.Raycast (player.position, player.TransformDirection(Vector3.down), out hit)) 
{ 
    if(hit.transform.name.Contains("MovingPlatform")) 
    { 
     Transform movingPlatform = hit.collider.transform; 

     if(movingPlatform.position.y - player.position.y <= min && movingPlatform.position.y - player.position.y >= max) 
     { 
      isOnMovingPlatform = true; 
     } 
     else 
     { 
      isOnMovingPlatform = false; 
     } 
    } 

    if(isOnMovingPlatform) 
    { 
     player.position = new Vector3(hit.transform.x, hit.transform.y + offsetToKeepPlayerAbovePlatform, 0); 
    } 
} 
} 
+0

Chỉ tò mò khi tôi sắp thử điều này, min, max và offset, chúng có liên quan đến kích thước của nền tảng không? – muttley91

+0

Không nhất thiết. Min và max chỉ là phạm vi để bạn biết vị trí của người chơi có liên quan đến nền tảng. Ví dụ: nếu giá trị Y của người chơi cao hơn 5 ở trên, thì rõ ràng anh ta không ở trên nền tảng và ngược lại. Thay đổi phạm vi cho đến khi bạn nhận được một cặp nổi. Về lý thuyết chúng có thể xuất phát từ chiều cao của nền tảng nhưng chúng không phải. –

0

This Unity Answers page có thể hữu ích.

+0

Nó thực sự khá tốt. Nhưng bạn nên đăng nó như bình luận hoặc cung cấp thêm thông tin. Câu trả lời chỉ chứa một liên kết sẽ bị giết trên SO (tôi vừa mất một số) – Kay

0

Bạn cũng có thể chỉ đơn giản là biến người chơi trò chơi biến đổi cha mẹ bằng với biến đổi của nền tảng. Điều này cho phép người chơi vẫn tiếp tục di chuyển trong khi họ đang ở trên đó. Đối với phát hiện một Raycast là một chút chậm nhưng được công việc làm.

0

Chúng tôi đã giải quyết vấn đề bằng cách sử dụng SliderJoint2d và đặt tỷ lệ trọng số của ký tự thành 0 trong khi đang di chuyển trên nền tảng. Dưới đây là liên kết với toàn bộ lời giải thích:

http://spacelizardstudio.com/devblog/index.php/2016/03/02/unity-a-guide-to-moving-platforms/

+0

Bạn nên thêm thông tin liên quan từ liên kết để câu trả lời vẫn hữu ích và có liên quan ngay cả khi liên kết bị chết. – drneel

Các vấn đề liên quan