그래서 Mike Hunt, 귀하의 질문에 관심이 있으니 완전한 솔루션을 구현하기로 결정했습니다. 다른 일을 시도한 세 시간 후에, 나는이 단계별 솔루션으로 끝났습니다.
(이 코드는 좋은 코드가 아니므로 편집을 수락합니다.)
컨텐츠 패널 만들기
(이 패널은 컨텍스트 메뉴 버튼을위한 컨테이너입니다)
- 새로 만들기
UI Panel
anchor
왼쪽 아래로 설정
width
300으로 설정 (원하는대로)
- 패널에 새로운 구성 요소를 추가
Vertical Layout Group
및 세트 Child Alignment
, 상부 중앙 Child Force Expand
(신장되지 않음) 대 폭
- 새 구성 요소를 패널에 추가하고 최소 크기로
Content Size Fitter
설정Vertical Fit
- 조립식으로 저장
(이 시점에서 패널은 줄로 줄어 듭니다. 정상입니다.이 패널은 버튼을 자식으로 받아들이고, 수직으로 정렬하고 요약 내용 높이로 확장합니다)
샘플 버튼 만들기
(이 버튼은 상황에 맞는 메뉴 항목을 표시하도록 인스턴스화되고 사용자 정의됩니다)
- 새로운 UI 버튼 만들기
anchor
왼쪽 상단으로 설정
- 버튼에 새 구성 요소 추가
Layout Element
설정 Min Height
, 30을 Preferred Height
30로
- 조립식으로 저장
ContextMenu.cs 스크립트 작성
(이 스크립트에는 상황에 맞는 메뉴를 만들고 표시하는 방법이 있습니다)
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
[System.Serializable]
public class ContextMenuItem
{
// this class - just a box to some data
public string text; // text to display on button
public Button button; // sample button prefab
public Action<Image> action; // delegate to method that needs to be executed when button is clicked
public ContextMenuItem(string text, Button button, Action<Image> action)
{
this.text = text;
this.button = button;
this.action = action;
}
}
public class ContextMenu : MonoBehaviour
{
public Image contentPanel; // content panel prefab
public Canvas canvas; // link to main canvas, where will be Context Menu
private static ContextMenu instance; // some kind of singleton here
public static ContextMenu Instance
{
get
{
if(instance == null)
{
instance = FindObjectOfType(typeof(ContextMenu)) as ContextMenu;
if(instance == null)
{
instance = new ContextMenu();
}
}
return instance;
}
}
public void CreateContextMenu(List<ContextMenuItem> items, Vector2 position)
{
// here we are creating and displaying Context Menu
Image panel = Instantiate(contentPanel, new Vector3(position.x, position.y, 0), Quaternion.identity) as Image;
panel.transform.SetParent(canvas.transform);
panel.transform.SetAsLastSibling();
panel.rectTransform.anchoredPosition = position;
foreach(var item in items)
{
ContextMenuItem tempReference = item;
Button button = Instantiate(item.button) as Button;
Text buttonText = button.GetComponentInChildren(typeof(Text)) as Text;
buttonText.text = item.text;
button.onClick.AddListener(delegate { tempReference.action(panel); });
button.transform.SetParent(panel.transform);
}
}
}
- 이 스크립트를 캔버스에 첨부하고 필드를 채우십시오.
ContentPanel
프리 팹을 해당 슬롯으로 드래그 앤 드롭 하고 캔버스 자체를 슬롯으로 드래그합니다 Canvas
.
ItemController.cs 스크립트 작성
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class ItemController : MonoBehaviour
{
public Button sampleButton; // sample button prefab
private List<ContextMenuItem> contextMenuItems; // list of items in menu
void Awake()
{
// Here we are creating and populating our future Context Menu.
// I do it in Awake once, but as you can see,
// it can be edited at runtime anywhere and anytime.
contextMenuItems = new List<ContextMenuItem>();
Action<Image> equip = new Action<Image>(EquipAction);
Action<Image> use = new Action<Image>(UseAction);
Action<Image> drop = new Action<Image>(DropAction);
contextMenuItems.Add(new ContextMenuItem("Equip", sampleButton, equip));
contextMenuItems.Add(new ContextMenuItem("Use", sampleButton, use));
contextMenuItems.Add(new ContextMenuItem("Drop", sampleButton, drop));
}
void OnMouseOver()
{
if(Input.GetMouseButtonDown(1))
{
Vector3 pos = Camera.main.WorldToScreenPoint(transform.position);
ContextMenu.Instance.CreateContextMenu(contextMenuItems, new Vector2(pos.x, pos.y));
}
}
void EquipAction(Image contextPanel)
{
Debug.Log("Equipped");
Destroy(contextPanel.gameObject);
}
void UseAction(Image contextPanel)
{
Debug.Log("Used");
Destroy(contextPanel.gameObject);
}
void DropAction(Image contextPanel)
{
Debug.Log("Dropped");
Destroy(contextPanel.gameObject);
}
}
- 장면 (예 :)에서 샘플 오브젝트를 생성
Cube
하고 카메라에 보이도록 배치하고이 스크립트를 첨부합니다. sampleButton
프리 팹을 해당 슬롯으로 드래그 앤 드롭 합니다.
이제 실행 해보십시오. 객체를 마우스 오른쪽 버튼으로 클릭하면 작성한 목록으로 채워진 상황에 맞는 메뉴가 나타납니다. 버튼을 누르면 일부 텍스트가 콘솔에 인쇄되고 상황에 맞는 메뉴가 손상됩니다.
가능한 개선 사항 :
- 훨씬 더 일반적인!
- 더 나은 메모리 관리 (더러운 링크, 패널을 파괴하지 않고 비활성화)
- 멋진 물건
샘플 프로젝트 (Unity Personal 5.2.0, VisualStudio Plugin) :
https://drive.google.com/file/d/0B7iGjyVbWvFwUnRQRVVaOGdDc2M/view?usp=sharing