#c# #unity3d #colors
Вопрос:
private Color solveColor;
void Start()
{
Color[] colors = { Color.cyan, Color.red, Color.green, new Color(245, 195, 29), Color.yellow, Color.magenta };
int lengthOfColors = colors.Length;
int solveColor = UnityEngine.Random.Range(0, lengthOfColors);
}
private void start()
{
GetComponent<MeshRenderer>().material.color = solveColor;
}
private void FixedUpdate()
{
// Set the balls speed when it should travel
if (isTraveling) {
rb.velocity = travelDirection * speed;
}
// Paint the ground
Collider[] hitColliders = Physics.OverlapSphere(transform.position - (Vector3.up/2), .05f);
int i = 0;
while (i < hitColliders.Length)
{
GroundPiece ground = hitColliders[i].transform.GetComponent<GroundPiece>();
if (ground amp;amp; !ground.isColored)
{
ground.Colored(solveColor);
}
Приведенный выше код должен выбрать один цвет из массива цветов и назначить его как способности к рисованию мяча, так и шаров (всякий раз, когда мяч сталкивается с землей, он меняет свой цвет), однако краска, которую оставляет мяч, всегда черная, а сам мяч всегда оранжевый (почти уверен, что цвет шара по умолчанию). Я не могу понять, почему это происходит, любая помощь очень ценится.
Спасибо, что уделили мне время
Ответ №1:
В предоставленном вами коде вы нигде больше не указываете цвет материала шара, кроме Start
как . Если вы хотите, чтобы частицы за шаром оставляли разные цвета, вам нужно будет создать новый экземпляр материала. Причина этого в том, что материалы в Unity по умолчанию являются общими для всех экземпляров этого конкретного материала.
Всю эту информацию и немного больше можно найти на странице Material
документов.
Поскольку у вас есть фиксированный размер используемых цветов, я бы вместо этого создал 6 новых материалов и вместо этого создал массив материалов. Теперь вместо того, чтобы случайным образом выбирать цвет, выберите материал и назначьте его мячу или вашей новой способности к рисованию. Я также не понимаю, почему вы размещаете свой массив цветов внутри своей Start
функции. Только тогда он будет локализован для этой функции. У вас также, похоже, есть две Start
функции, что странно. Одно из Start
них-Однобокое, а другое-другое start
. Если это не предусмотрено, ваш второй start
не будет запущен, пока вы его не вызовете.
Теперь перейдем к решению, о котором я говорил.
// assign these in the inspector to your new materials
[SerializeField] private List<Material> materials = new List<Material>();
private MeshRenderer meshRender;
private void Start()
{
meshRenderer = GetComponent<MeshRenderer>();
// set our first random Material
SetNewMaterialColor();
}
private void SetNewMaterialColor()
{
meshRenderer.material = GrabNewMaterial();
}
private void FixedUpdate()
{
// Set the balls speed when it should travel
if (isTraveling) {
rb.velocity = travelDirection * speed;
}
// Paint the ground
Collider[] hitColliders = Physics.OverlapSphere(transform.position - (Vector3.up/2), .05f);
int i = 0;
while (i < hitColliders.Length)
{
GroundPiece ground = hitColliders[i].transform.GetComponent<GroundPiece>();
if (ground amp;amp; !ground.isColored)
{
// change this from a color to a material instead
ground.Colored(meshRenderer.material);
// set a new material to your main object
SetNewMaterialColor();
}
}
}
private Material GrabNewMaterial()
{
return materials[UnityEngine.Random.Range(0, materials.Count)];
}
Вам нужно будет изменить свою Colored
функцию, чтобы использовать a Material
вместо a Color
. Если вы хотите, чтобы реализация была более динамичной, вы можете вместо этого создать экземпляр вашего материала и динамически задать цвет, но поскольку у вас фиксированный размер цветов, я не думаю, что вам нужно это делать.
Изменить: Еще один вариант, который включает в себя создание нового шейдера, — использовать [PerRendererData]
значение, означающее, что каждый объект для поля свойств отображается индивидуально. Я бы выбрал предыдущий вариант, так как любой из вариантов с использованием шейдеров или экземпляров материалов немного сложнее.
Вам нужно будет использовать a MaterialPropertyBlock
, а затем вы можете назначить цвет, когда захотите. Это выглядело бы примерно так
public void SetNewColor()
{
// create a new material property block
MaterialPropertyBlock tmpBlock = new MaterialPropertyBlock();
// grab the current block from our renderer
meshRender.GetPropertyBlock(tmpBlock);
// set our changes to the block
tmpBlock.SetColor("_Color", YourColorHere);
// now apply our changes
tmpRend.SetPropertyBlock(tmpBlock);
}
И вам нужно будет создать новый шейдер, который позже Main Color
будет использовать свойство с помощью PerRendererData
атрибута.
Properties
{
[PerRendererData]_Color("Main Color", Color) = (1,1,1,1)
...
Кроме того, у меня есть еще один вопрос: почему вы используете Physics.OverlapSphere
вместо просто an OnCollisionEnter
? Или если ваша игра 2D, то OnCollisionEnter2D
и пусть физический движок обрабатывает, как работают столкновения, а затем просто меняет цвета при столкновении?
Редактировать: Вот ответы на ваши вопросы — дайте мне знать, если у вас есть еще.
В строке «[SerializeField] материалы частного списка = новый список();» какой раздел мне нужно заменить материалами и как?
Линия как есть в порядке. С его помощью [SerializeField]
этот список открывается редактору. Вам понадобится создать несколько новых дубликатов материалов, в которых будут использованы ваши 6 различных цветов. Вместо того, чтобы задавать цвета, теперь вы будете задавать материалы. Что я подразумеваю под инспектором и редактором, так это то, что вы можете найти объект, на котором есть этот сценарий, в Unity, выбрать его (он должен быть сборным или в сцене), затем вкладка редактора Unity заполнится информацией об этом объекте. Найдите часть сценария и найдите поле materials
. Там должна быть стрелка раскрывающегося списка, нажмите на нее и установите значение 6
(или сколько бы материалов вы ни поменяли местами). Теперь создайте 6 новых материалов с вашими цветами и перетащите их в появившиеся поля.
Было бы это что-то вроде написания «./Материалы/Мяч 1» в (), например?
Нет! Вы будете назначать эти данные в инспекторе, поэтому данные будут храниться в списке без ссылок на них в коде.
И я не уверен, как назначить это моему мячу, используя «[SerializeField] частный игровой объект paintObject = null;»
Аналогично, это будет отображаться в инспекторе. Однако удалите эту строку, так как я неправильно понял ваш первоначальный вопрос и случайно оставил это. Я предположил, что ваш объект рисования был сборным, который вы создавали после того, как мяч отскочил, а не землей, цвет которой вы меняли.
Я получаю ошибку «Аргумент 1: не удается преобразовать из ‘UnityEngine.Материал» для «UnityEngine.Цвет»»
Да! Итак, как я уже упоминал в комментариях, ваш вызов функции для объекта paint, скорее всего, в настоящее время принимает Color
параметр. Поскольку я изменил вашу реализацию на вместо этого напрямую Material
, вам нужно будет изменить способ подписи этой функции. В частности, линия:
ground.Colored(meshRenderer.material);
У вас есть некоторый объект ground
, который имеет тип GroundPiece
и имеет вызываемую функцию Colored
. Я предполагаю, что в настоящее время это выглядит примерно так:
public void Colored(Color color){...}
Вы хотите изменить это вместо этого на:
public void Colored(Material mat{...}
После его изменения вместо изменения цвета грунта в этом сценарии вы бы изменили его материал напрямую. Дайте мне знать, если у вас возникнут еще вопросы.
Комментарии:
1. Большое вам спасибо за все ваши советы, я прочитал их и ссылки на материалы, которые вы предоставили, и еще несколько вопросов (извините, если это просто, я использую unity и c# только около 2 дней, так что я все еще не уверен в этом). В строке «[SerializeField] закрытый список<Материал> материалы = новый список<Материал><Материал>();» какой раздел мне нужно заменить материалами и как? Было бы это что-то вроде написания «./Материалы/Мяч 1» в (), например? И я не уверен, как назначить это моему мячу, используя «[SerializeField] частный игровой объект paintObject = null;», потому что
2. этот скрипт прикрепляется к самому мячу (он также управляет его движением при свайпе и т. Д.). Мой последний вопрос: почему я получаю ошибку «Аргумент 1: не удается преобразовать из ‘UnityEngine. Материал» для «UnityEngine. Цвет». Еще раз большое вам спасибо за всю вашу помощь, и мне жаль, если это простые/очевидные исправления. Хорошего вам дня!
3. Не беспокойтесь! Я отвечу на ваши вопросы по порядку в качестве обновленной части моего ответа.
4. Если вы не знакомы с инспектором, это выглядит примерно так . Как только вы нажмете на раскрывающийся список и увеличите количество, вы сможете перетащить
Material
ссылки на него.5. Спасибо тебе огромное, я бы никогда не догадался об этом без твоей помощи. Теперь это работает отлично, спасибо вам за ваше терпение и объяснения, я действительно ценю это, это именно то, что я искал!