Generating a QuestionID Using a Nested Loop for a Quiz Game
You ask for a refactoring of the current method. It could be:

public void saveToDB()
{
  int setID = 0;
  foreach (Set set in sets)
  {
    int brandID = 0;
    foreach (Brand brand in set.brands)
    {
      int questionID = 0;
      foreach (Question question in brand.questions)
      {
        PlayerPrefs.SetString(
          key: $"s{setID}|b{brandID}|q{questionID}",
          value: $"value:{set.setName}|{brand.brandName}|{question.questionID()}"); // save to the database

        questionID++;
      }
      brandID++;
    }
    setID++;
  }
}


Here is used string interpolation $"s{setID}...." instead of string concatenation which is considered to be bad practice because it results in too many string instantiations and is hard to read. 



It could be done by using LINQ, but that is maybe more confusing and will actually be slower:

public void saveToDB()
{
  var questionInfos = sets.SelectMany((set, setId) =&gt; set.brands.SelectMany((brand, brandId) =&gt; brand.questions.Select((question, questionId) =&gt; new { key = $"s{setId}|b{brandId}|q{questionId}", value = $"value:{set.setName}|{brand.brandName}|{question.questionID()}" })));

  foreach (var questionInfo in questionInfos)
  {
    PlayerPrefs.SetString(questionInfo.key, questionInfo.value);
  }
}


Just for the sport, it can be done in inline query syntax (with a little help from method syntax) as t3echb0t suggested:

public void saveToDB()
{
  var questionInfos = from setAndId in sets.Select((set, id) =&gt; (set, id))
                      from brandAndId in setAndId.set.brands.Select((brand, id) =&gt; (brand, id))
                      from questionAndId in brandAndId.brand.questions.Select((question, id) =&gt; (question, id))
                      select new
                      {
                        key = $"s{setAndId.id}|b{brandAndId.id}|q{questionAndId.id}",
                        value = $"value:{setAndId.set.setName}|{brandAndId.brand.brandName}|{questionAndId.question.questionID()}"
                      };

  foreach (var questionInfo in questionInfos)
  {
    PlayerPrefs.SetString(questionInfo.key, questionInfo.value);
  }
}




That said, I would consider an mandatory Id to be a property on each Set, Brand and Question instance:

public abstract class ObjectBase
{
  public ObjectBase(string name, int id)
  {
    Name = name;
    Id = id;
  }

  public string Name { get; }
  public int Id { get; }
}

public class Set : ObjectBase
{
  public Set(string name, int id) : base(name, id)
  {

  }

  public Brand[] Brands { get; set; }
}

public class Brand : ObjectBase
{
  public Brand(string name, int id) : base(name, id)
  {

  }

  public Question[] Questions { get; set; }
}

public class Question : ObjectBase
{
  public int FontSize;
  public string[] Choices = new string[3];  //choices for each question
  public readonly int CorrectAnswerId;  //will hold the correct answer for a question

  public Question(string question, int correctAnswerId, string[] choices, int id) : base(question, id)
  {
    CorrectAnswerId = correctAnswerId;
    Choices = choices;
  }

  public string TheQuestion =&gt; Name;

  public string QuestionID()
  {
    // making a id for question
    return $"{TheQuestion}|{string.Join("|", Choices)}|{CorrectAnswerId}|{FontSize}";
  }

}


public class QuestionManager //: MonoBehaviour
{
  Set[] sets = new Set[0];

  public void saveToDB()
  {
    foreach (Set set in sets)
    {
      foreach (Brand brand in set.Brands)
      {
        foreach (Question question in brand.Questions)
        {
          PlayerPrefs.SetString(
            key: $"s{set.Id}|b{brand.Id}|q{question.Id}",
            value: $"value:{set.Name}|{brand.Name}|{question.QuestionID()}"); // save to the database
        }
      }
    }
  }
}


Notice here that there is no point in calling the name of a Set "setName - Name is sufficient.
Further notice that it is common practice in C# to use PascalCase for public members.

The benefit of having the entities be born with an id, is that you can use that id to identify each instance uniquely throughout the session/lifetime of each object. And as shown the key/value-pair for PlayerPrefs.SetString is easier created.