Skip to content

Trying to implement the "pick up" and "put down" object actions #714

@basteran

Description

@basteran

Hi, thanks for the great work. This tool looks very interesting and I was trying to implement the "pick up" and "put down" object actions as in your documentation and tutorials (btw they are great!) you mention that these are not built-in.

I am facing some issues when executing the "pick up" action. This is the error from Python.

The build quit due to an error. Check the build log for more info.
If the build is on the same machine as this controller, the log path is probably C:\Users\user\AppData\Local\Unity\Editor\Editor.log
If the build is on a remote Linux server, the log path is probably ~/.config/unity3d/MIT/TDW/Player.log (where ~ is your home directory)        

Here I paste my code, maybe you can give me some feedback or ideas.

from tdw.controller import Controller
from tdw.add_ons.floorplan import Floorplan
from tdw.add_ons.first_person_avatar import FirstPersonAvatar
from tdw.output_data import OutputData, Transforms


"""
Generate a floorplan scene and populate it with a layout of objects.
User implementation of "pick up" and "put down" actions.
"""

c = Controller()
a = FirstPersonAvatar(position={"x": 0, "y": 0, "z": 4})

# Initialize the floorplan add-on.
floorplan = Floorplan()
# Scene 5, visual variant c, object layout 2.
floorplan.init_scene(scene="5c", layout=2)

c.add_ons.extend([floorplan, a])
# Initialize the scene.
c.communicate([])
# Make the image 1080p and hide the roof.
# c.communicate([{"$type": "set_screen_size",
#                 "width": 1920,
#                 "height": 1080}])
c.communicate([{"$type": "set_screen_size",
                "width": 1280,
                "height": 720}])


def calculate_distance(position1, position2):
    return ((position1['x'] - position2['x'])**2 + (position1['y'] - position2['y'])**2 + (position1['z'] - position2['z'])**2) ** 0.5

def get_object_position(object_id):
    resp = c.communicate({"$type": "send_transforms", "ids": [object_id]})
    for r in resp:
        # Check if this part of the response is a "Transforms" message
        if OutputData.get_data_type_id(r) == "tran":
            transforms = Transforms(r)
            for i in range(transforms.get_num()):
                object_id_from_response = transforms.get_id(i)
                if object_id_from_response == object_id:
                    position_list = transforms.get_position(i).tolist()
                    return {
                        "x": position_list[0],
                        "y": position_list[1],
                        "z": position_list[2]
                    }


def get_avatar_current_position():
    global a
    return {"x": a.transform.position.tolist()[0], "y": a.transform.position.tolist()[1], "z": a.transform.position.tolist()[2]}


done = False
grasp_range = 2.0  # Define grasp range
held_object_id = None  # Variable to store the object ID if holding one

while not done:
    c.communicate([])

    if a.left_button_pressed:
        if held_object_id is not None:
            # Drop the currently held object
            c.communicate({"$type": "drop_object", "id": held_object_id})
            held_object_id = None  # Reset the held object
        elif a.mouse_is_over_object:
            object_id = a.mouse_over_object_id
            object_position = get_object_position(object_id)  # function to get object's position
            # Calculate distance between avatar and object
            avatar_position = get_avatar_current_position()
            distance = calculate_distance(avatar_position, object_position)
            
            # Only grasp the object if it's within range
            if distance <= grasp_range:
                # Grasp the object
                c.communicate({"$type": "grasp_object", "id": object_id, "grasping_avatar": a.avatar_id})
                held_object_id = object_id  # Store the held object ID
                print(f"Grasped object '{held_object_id}'")
            else:
                print("Object is out of range!")
    
    if a.right_button_pressed:
        done = True

        
c.communicate({"$type": "terminate"})

Now the error says to check the Editor.log file and it's empty! Do you have any ideas or feedback? Is this feasible? Or do you know any implementation of it?

Thank you once again!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions